Update to 2.5

Updated using ./update_source.sh 2.5

Bug: 32912773
Test: Does not build yet; see following commit
Change-Id: I88f6252c2b17ea6c69255e7a607678fc9fa541a5
diff --git a/README.version b/README.version
index 614fcde..95ae353 100644
--- a/README.version
+++ b/README.version
@@ -1,6 +1,6 @@
 URL: https://github.com/easymock/objenesis
-Version: 2.0
+Version: 2.5
 BugComponent: 21001
 
 Local Modifications:
-      None
+        None
diff --git a/main/.settings/org.eclipse.jdt.core.prefs b/main/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 302c5cb..0000000
--- a/main/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,296 +0,0 @@
-eclipse.preferences.version=1

-org.eclipse.jdt.core.codeComplete.argumentPrefixes=

-org.eclipse.jdt.core.codeComplete.argumentSuffixes=

-org.eclipse.jdt.core.codeComplete.fieldPrefixes=

-org.eclipse.jdt.core.codeComplete.fieldSuffixes=

-org.eclipse.jdt.core.codeComplete.localPrefixes=

-org.eclipse.jdt.core.codeComplete.localSuffixes=

-org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=

-org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=

-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.3

-org.eclipse.jdt.core.compiler.compliance=1.3

-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning

-org.eclipse.jdt.core.compiler.source=1.3

-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16

-org.eclipse.jdt.core.formatter.alignment_for_assignment=0

-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16

-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16

-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80

-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0

-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16

-org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0

-org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16

-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80

-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16

-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0

-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16

-org.eclipse.jdt.core.formatter.blank_lines_after_imports=1

-org.eclipse.jdt.core.formatter.blank_lines_after_package=1

-org.eclipse.jdt.core.formatter.blank_lines_before_field=0

-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0

-org.eclipse.jdt.core.formatter.blank_lines_before_imports=1

-org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1

-org.eclipse.jdt.core.formatter.blank_lines_before_method=1

-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1

-org.eclipse.jdt.core.formatter.blank_lines_before_package=0

-org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1

-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1

-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line

-org.eclipse.jdt.core.formatter.comment.clear_blank_lines=true

-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true

-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true

-org.eclipse.jdt.core.formatter.comment.format_block_comments=true

-org.eclipse.jdt.core.formatter.comment.format_comments=true

-org.eclipse.jdt.core.formatter.comment.format_header=false

-org.eclipse.jdt.core.formatter.comment.format_html=true

-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true

-org.eclipse.jdt.core.formatter.comment.format_line_comments=true

-org.eclipse.jdt.core.formatter.comment.format_source_code=true

-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false

-org.eclipse.jdt.core.formatter.comment.indent_root_tags=true

-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert

-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert

-org.eclipse.jdt.core.formatter.comment.line_length=100

-org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true

-org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true

-org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false

-org.eclipse.jdt.core.formatter.compact_else_if=true

-org.eclipse.jdt.core.formatter.continuation_indentation=1

-org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=1

-org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off

-org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on

-org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false

-org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true

-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true

-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true

-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true

-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true

-org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true

-org.eclipse.jdt.core.formatter.indent_empty_lines=false

-org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true

-org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true

-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true

-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false

-org.eclipse.jdt.core.formatter.indentation.size=3

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert

-org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert

-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert

-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert

-org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert

-org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert

-org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert

-org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert

-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert

-org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert

-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert

-org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert

-org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert

-org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert

-org.eclipse.jdt.core.formatter.join_lines_in_comments=true

-org.eclipse.jdt.core.formatter.join_wrapped_lines=true

-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false

-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false

-org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false

-org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false

-org.eclipse.jdt.core.formatter.lineSplit=100

-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false

-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false

-org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0

-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1

-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true

-org.eclipse.jdt.core.formatter.tabulation.char=space

-org.eclipse.jdt.core.formatter.tabulation.size=3

-org.eclipse.jdt.core.formatter.use_on_off_tags=false

-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false

-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true

-org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true

-org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

diff --git a/main/.settings/org.eclipse.jdt.ui.prefs b/main/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index cdfe61e..0000000
--- a/main/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,10 +0,0 @@
-eclipse.preferences.version=1

-formatter_profile=_Objenesis

-formatter_settings_version=12

-internal.default.compliance=user

-org.eclipse.jdt.ui.exception.name=e

-org.eclipse.jdt.ui.gettersetter.use.is=true

-org.eclipse.jdt.ui.javadoc=false

-org.eclipse.jdt.ui.keywordthis=false

-org.eclipse.jdt.ui.overrideannotation=true

-org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>

diff --git a/main/assembly.xml b/main/assembly.xml
index 0c28778..8e9c3b3 100644
--- a/main/assembly.xml
+++ b/main/assembly.xml
@@ -1,40 +1,40 @@
-<!--

-

-    Copyright 2006-2013 the original author or authors.

-

-    Licensed under the Apache License, Version 2.0 (the "License");

-    you may not use this file except in compliance with the License.

-    You may obtain a copy of the License at

-

-        http://www.apache.org/licenses/LICENSE-2.0

-

-    Unless required by applicable law or agreed to in writing, software

-    distributed under the License is distributed on an "AS IS" BASIS,

-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-    See the License for the specific language governing permissions and

-    limitations under the License.

-

--->

-<assembly>

-  <id>bin</id>

-  <formats>

-    <format>zip</format>

-  </formats>

-  <fileSets>

-    <fileSet>

-      <directory>${project.build.outputDirectory}/META-INF</directory>

-      <outputDirectory>/</outputDirectory>

-      <includes>

-        <include>NOTICE</include>

-        <include>LICENSE</include>

-      </includes>

-    </fileSet>

-    <fileSet>

-      <directory>${project.build.directory}</directory>

-      <outputDirectory>/</outputDirectory>

-      <includes>

-        <include>*.jar</include>

-      </includes>

-    </fileSet>

-  </fileSets>

+<!--
+
+    Copyright 2006-2017 the original author or authors.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<assembly>
+  <id>bin</id>
+  <formats>
+    <format>zip</format>
+  </formats>
+  <fileSets>
+    <fileSet>
+      <directory>${project.build.outputDirectory}/META-INF</directory>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <include>NOTICE</include>
+        <include>LICENSE</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>${project.build.directory}</directory>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <include>*.jar</include>
+      </includes>
+    </fileSet>
+  </fileSets>
 </assembly>
\ No newline at end of file
diff --git a/main/pom.xml b/main/pom.xml
index 10f993b..3af2ef4 100644
--- a/main/pom.xml
+++ b/main/pom.xml
@@ -1,78 +1,90 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>

-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

-  <modelVersion>4.0.0</modelVersion>

-  <parent>

-    <groupId>org.objenesis</groupId>

-    <artifactId>objenesis-parent</artifactId>

-    <version>2.0-SNAPSHOT</version>

-  </parent>

-  <artifactId>objenesis</artifactId>

-  

-  <name>Objenesis</name>

-  <description>A library for instantiating Java objects</description>

-  <url>http://objenesis.org</url>

-

-  <dependencies />

-

-  <build>

-    <plugins>

-      <plugin>

-        <groupId>com.keyboardsamurais.maven</groupId>

-        <artifactId>maven-timestamp-plugin</artifactId>

-      </plugin>

-      <plugin>

-        <groupId>com.google.code.maven-license-plugin</groupId>

-        <artifactId>maven-license-plugin</artifactId>

-      </plugin>

-      <plugin>

-        <groupId>org.apache.maven.plugins</groupId>

-        <artifactId>maven-remote-resources-plugin</artifactId>

-      </plugin>

-      <plugin>

-        <groupId>org.apache.felix</groupId>

-        <artifactId>maven-bundle-plugin</artifactId>

-        <extensions>true</extensions>

-        <configuration>

-          <instructions>

-            <Import-Package>

-            COM.jrockit.reflect;resolution:=optional,

-            jrockit.vm;resolution:=optional,

-            COM.newmonics.PercClassloader;resolution:=optional,

-            sun.reflect;resolution:=optional

-            </Import-Package>

-          </instructions>

-        </configuration>

-      </plugin>

-    </plugins>

-  </build>

-

-  <profiles>

-    <profile>

-      <!-- Activate to create the release bundle -->

-      <id>release</id>

-      <build>

-        <plugins>

-          <plugin>

-            <groupId>org.apache.maven.plugins</groupId>

-            <artifactId>maven-assembly-plugin</artifactId>

-            <configuration>

-              <attach>false</attach>

-              <descriptors>

-                <descriptor>assembly.xml</descriptor>

-              </descriptors>

-            </configuration>

-            <executions>

-              <execution>

-                <id>make-assembly</id>

-                <phase>package</phase>

-                <goals>

-                  <goal>single</goal>

-                </goals>

-              </execution>

-            </executions>

-          </plugin>

-        </plugins>

-      </build>

-    </profile>

-  </profiles>

-</project>

+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.objenesis</groupId>
+    <artifactId>objenesis-parent</artifactId>
+    <version>2.5</version>
+  </parent>
+  <artifactId>objenesis</artifactId>
+
+  <name>Objenesis</name>
+  <description>A library for instantiating Java objects</description>
+  <url>http://objenesis.org</url>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>com.keyboardsamurais.maven</groupId>
+        <artifactId>maven-timestamp-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>com.mycila.maven-license-plugin</groupId>
+        <artifactId>maven-license-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-remote-resources-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Import-Package>
+            COM.newmonics.PercClassloader;resolution:=optional,
+            sun.misc;resolution:=optional,
+            sun.reflect;resolution:=optional
+            </Import-Package>
+          </instructions>
+        </configuration>
+        <executions>
+          <execution>
+            <id>bundle-manifest</id>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>manifest</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+    <profile>
+      <!-- Activate to create the release bundle -->
+      <id>release</id>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-assembly-plugin</artifactId>
+            <configuration>
+              <attach>false</attach>
+              <descriptors>
+                <descriptor>assembly.xml</descriptor>
+              </descriptors>
+            </configuration>
+            <executions>
+              <execution>
+                <id>make-assembly</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>single</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/main/src/main/java/org/objenesis/Objenesis.java b/main/src/main/java/org/objenesis/Objenesis.java
index 8bb29a5..893d426 100644
--- a/main/src/main/java/org/objenesis/Objenesis.java
+++ b/main/src/main/java/org/objenesis/Objenesis.java
@@ -1,44 +1,46 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis;

-

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Common interface to all kind of Objenesis objects

- * 

- * @author Henri Tremblay

- */

-public interface Objenesis {

-

-   /**

-    * Will create a new object without any constructor being called

-    * 

-    * @param clazz Class to instantiate

-    * @return New instance of clazz

-    */

-   Object newInstance(Class clazz);

-

-   /**

-    * Will pick the best instantiator for the provided class. If you need to create a lot of

-    * instances from the same class, it is way more efficient to create them from the same

-    * ObjectInstantiator than calling {@link #newInstance(Class)}.

-    * 

-    * @param clazz Class to instantiate

-    * @return Instantiator dedicated to the class

-    */

-   ObjectInstantiator getInstantiatorOf(Class clazz);

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import org.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Common interface to all kind of Objenesis objects
+ * 
+ * @author Henri Tremblay
+ */
+public interface Objenesis {
+
+   /**
+    * Will create a new object without any constructor being called
+    *
+    * @param <T> Type instantiated
+    * @param clazz Class to instantiate
+    * @return New instance of clazz
+    */
+   <T> T newInstance(Class<T> clazz);
+
+   /**
+    * Will pick the best instantiator for the provided class. If you need to create a lot of
+    * instances from the same class, it is way more efficient to create them from the same
+    * ObjectInstantiator than calling {@link #newInstance(Class)}.
+    *
+    * @param <T> Type to instantiate
+    * @param clazz Class to instantiate
+    * @return Instantiator dedicated to the class
+    */
+   <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz);
+}
diff --git a/main/src/main/java/org/objenesis/ObjenesisBase.java b/main/src/main/java/org/objenesis/ObjenesisBase.java
index 24bb444..7427200 100644
--- a/main/src/main/java/org/objenesis/ObjenesisBase.java
+++ b/main/src/main/java/org/objenesis/ObjenesisBase.java
@@ -1,96 +1,102 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis;

-

-import java.util.HashMap;

-import java.util.Map;

-

-import org.objenesis.instantiator.ObjectInstantiator;

-import org.objenesis.strategy.InstantiatorStrategy;

-

-/**

- * Base class to extend if you want to have a class providing your own default strategy. Can also be

- * instantiated directly.

- * 

- * @author Henri Tremblay

- */

-public class ObjenesisBase implements Objenesis {

-

-   /** Strategy used by this Objenesi implementation to create classes */

-   protected final InstantiatorStrategy strategy;

-

-   /** Strategy cache. Key = Class, Value = InstantiatorStrategy */

-   protected Map cache;

-

-   /**

-    * Constructor allowing to pick a strategy and using cache

-    * 

-    * @param strategy Strategy to use

-    */

-   public ObjenesisBase(InstantiatorStrategy strategy) {

-      this(strategy, true);

-   }

-

-   /**

-    * Flexible constructor allowing to pick the strategy and if caching should be used

-    * 

-    * @param strategy Strategy to use

-    * @param useCache If {@link ObjectInstantiator}s should be cached

-    */

-   public ObjenesisBase(InstantiatorStrategy strategy, boolean useCache) {

-      if(strategy == null) {

-         throw new IllegalArgumentException("A strategy can't be null");

-      }

-      this.strategy = strategy;

-      this.cache = useCache ? new HashMap() : null;

-   }

-

-   public String toString() {

-      return getClass().getName() + " using " + strategy.getClass().getName()

-         + (cache == null ? " without" : " with") + " caching";

-   }

-

-   /**

-    * Will create a new object without any constructor being called

-    * 

-    * @param clazz Class to instantiate

-    * @return New instance of clazz

-    */

-   public Object newInstance(Class clazz) {

-      return getInstantiatorOf(clazz).newInstance();

-   }

-

-   /**

-    * Will pick the best instantiator for the provided class. If you need to create a lot of

-    * instances from the same class, it is way more efficient to create them from the same

-    * ObjectInstantiator than calling {@link #newInstance(Class)}.

-    * 

-    * @param clazz Class to instantiate

-    * @return Instantiator dedicated to the class

-    */

-   public synchronized ObjectInstantiator getInstantiatorOf(Class clazz) {

-      if(cache == null) {

-         return strategy.newInstantiatorOf(clazz);

-      }

-      ObjectInstantiator instantiator = (ObjectInstantiator) cache.get(clazz.getName());

-      if(instantiator == null) {

-         instantiator = strategy.newInstantiatorOf(clazz);

-         cache.put(clazz.getName(), instantiator);

-      }

-      return instantiator;

-   }

-

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.strategy.InstantiatorStrategy;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Base class to extend if you want to have a class providing your own default strategy. Can also be
+ * instantiated directly.
+ *
+ * @author Henri Tremblay
+ */
+public class ObjenesisBase implements Objenesis {
+
+   /** Strategy used by this Objenesi implementation to create classes */
+   protected final InstantiatorStrategy strategy;
+
+   /** Strategy cache. Key = Class, Value = InstantiatorStrategy */
+   protected ConcurrentHashMap<String, ObjectInstantiator<?>> cache;
+
+   /**
+    * Constructor allowing to pick a strategy and using cache
+    *
+    * @param strategy Strategy to use
+    */
+   public ObjenesisBase(InstantiatorStrategy strategy) {
+      this(strategy, true);
+   }
+
+   /**
+    * Flexible constructor allowing to pick the strategy and if caching should be used
+    *
+    * @param strategy Strategy to use
+    * @param useCache If {@link ObjectInstantiator}s should be cached
+    */
+   public ObjenesisBase(InstantiatorStrategy strategy, boolean useCache) {
+      if(strategy == null) {
+         throw new IllegalArgumentException("A strategy can't be null");
+      }
+      this.strategy = strategy;
+      this.cache = useCache ? new ConcurrentHashMap<String, ObjectInstantiator<?>>() : null;
+   }
+
+   @Override
+   public String toString() {
+      return getClass().getName() + " using " + strategy.getClass().getName()
+         + (cache == null ? " without" : " with") + " caching";
+   }
+
+   /**
+    * Will create a new object without any constructor being called
+    *
+    * @param clazz Class to instantiate
+    * @return New instance of clazz
+    */
+   public <T> T newInstance(Class<T> clazz) {
+      return getInstantiatorOf(clazz).newInstance();
+   }
+
+   /**
+    * Will pick the best instantiator for the provided class. If you need to create a lot of
+    * instances from the same class, it is way more efficient to create them from the same
+    * ObjectInstantiator than calling {@link #newInstance(Class)}.
+    *
+    * @param clazz Class to instantiate
+    * @return Instantiator dedicated to the class
+    */
+   @SuppressWarnings("unchecked")
+   public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) {
+      if(clazz.isPrimitive()) {
+         throw new IllegalArgumentException("Primitive types can't be instantiated in Java");
+      }
+      if(cache == null) {
+         return strategy.newInstantiatorOf(clazz);
+      }
+      ObjectInstantiator<?> instantiator = cache.get(clazz.getName());
+      if(instantiator == null) {
+         ObjectInstantiator<?> newInstantiator = strategy.newInstantiatorOf(clazz);
+         instantiator = cache.putIfAbsent(clazz.getName(), newInstantiator);
+         if(instantiator == null) {
+            instantiator = newInstantiator;
+         }
+      }
+      return (ObjectInstantiator<T>) instantiator;
+   }
+}
diff --git a/main/src/main/java/org/objenesis/ObjenesisException.java b/main/src/main/java/org/objenesis/ObjenesisException.java
index f192dbe..3ae54dd 100644
--- a/main/src/main/java/org/objenesis/ObjenesisException.java
+++ b/main/src/main/java/org/objenesis/ObjenesisException.java
@@ -1,59 +1,49 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis;

-

-/**

- * Exception thrown by Objenesis. It wraps any instantiation exceptions. Note that this exception is

- * runtime to prevent having to catch it. It will do normal exception wrapping for JDK 1.4 and more

- * and basic message wrapping for JDK 1.3.

- * 

- * @author Henri Tremblay

- */

-public class ObjenesisException extends RuntimeException {

-

-   private static final long serialVersionUID = -2677230016262426968L;

-   

-   private static final boolean jdk14 = (Double.parseDouble(System

-      .getProperty("java.specification.version")) > 1.3);

-

-   /**

-    * @param msg Error message

-    */

-   public ObjenesisException(String msg) {

-      super(msg);

-   }

-

-   /**

-    * @param cause Wrapped exception. The message will be the one of the cause.

-    */

-   public ObjenesisException(Throwable cause) {

-      super(cause == null ? null : cause.toString());

-      if(jdk14) {

-         initCause(cause);

-      }

-   }

-

-   /**

-    * @param msg Error message

-    * @param cause Wrapped exception

-    */

-   public ObjenesisException(String msg, Throwable cause) {

-      super(msg);

-      if(jdk14) {

-         initCause(cause);

-      }

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+/**
+ * Exception thrown by Objenesis. It wraps any instantiation exceptions. Note that this exception is
+ * runtime to prevent having to catch it.
+ * 
+ * @author Henri Tremblay
+ */
+public class ObjenesisException extends RuntimeException {
+
+   private static final long serialVersionUID = -2677230016262426968L;
+   
+   /**
+    * @param msg Error message
+    */
+   public ObjenesisException(String msg) {
+      super(msg);
+   }
+
+   /**
+    * @param cause Wrapped exception. The message will be the one of the cause.
+    */
+   public ObjenesisException(Throwable cause) {
+      super(cause);
+   }
+
+   /**
+    * @param msg Error message
+    * @param cause Wrapped exception
+    */
+   public ObjenesisException(String msg, Throwable cause) {
+      super(msg, cause);
+   }
+}
diff --git a/main/src/main/java/org/objenesis/ObjenesisHelper.java b/main/src/main/java/org/objenesis/ObjenesisHelper.java
index 2e86305..8a947f3 100644
--- a/main/src/main/java/org/objenesis/ObjenesisHelper.java
+++ b/main/src/main/java/org/objenesis/ObjenesisHelper.java
@@ -1,80 +1,84 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis;

-

-import java.io.Serializable;

-

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Use Objenesis in a static way. <strong>It is strongly not recommended to use this class.</strong>

- * 

- * @author Henri Tremblay

- */

-public final class ObjenesisHelper {

-

-   private static final Objenesis OBJENESIS_STD = new ObjenesisStd();

-

-   private static final Objenesis OBJENESIS_SERIALIZER = new ObjenesisSerializer();

-

-   private ObjenesisHelper() {

-   }

-

-   /**

-    * Will create a new object without any constructor being called

-    * 

-    * @param clazz Class to instantiate

-    * @return New instance of clazz

-    */

-   public static Object newInstance(Class clazz) {

-      return OBJENESIS_STD.newInstance(clazz);

-   }

-

-   /**

-    * Will create an object just like it's done by ObjectInputStream.readObject (the default

-    * constructor of the first non serializable class will be called)

-    * 

-    * @param clazz Class to instantiate

-    * @return New instance of clazz

-    */

-   public static Serializable newSerializableInstance(Class clazz) {

-      return (Serializable) OBJENESIS_SERIALIZER.newInstance(clazz);

-   }

-

-   /**

-    * Will pick the best instantiator for the provided class. If you need to create a lot of

-    * instances from the same class, it is way more efficient to create them from the same

-    * ObjectInstantiator than calling {@link #newInstance(Class)}.

-    * 

-    * @param clazz Class to instantiate

-    * @return Instantiator dedicated to the class

-    */

-   public static ObjectInstantiator getInstantiatorOf(Class clazz) {

-      return OBJENESIS_STD.getInstantiatorOf(clazz);

-   }

-

-   /**

-    * Same as {@link #getInstantiatorOf(Class)} but providing an instantiator emulating

-    * ObjectInputStream.readObject behavior.

-    * 

-    * @see #newSerializableInstance(Class)

-    * @param clazz Class to instantiate

-    * @return Instantiator dedicated to the class

-    */

-   public static ObjectInstantiator getSerializableObjectInstantiatorOf(Class clazz) {

-      return OBJENESIS_SERIALIZER.getInstantiatorOf(clazz);

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import java.io.Serializable;
+
+import org.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Use Objenesis in a static way. <strong>It is strongly not recommended to use this class.</strong>
+ * 
+ * @author Henri Tremblay
+ */
+public final class ObjenesisHelper {
+
+   private static final Objenesis OBJENESIS_STD = new ObjenesisStd();
+
+   private static final Objenesis OBJENESIS_SERIALIZER = new ObjenesisSerializer();
+
+   private ObjenesisHelper() {
+   }
+
+   /**
+    * Will create a new object without any constructor being called
+    *
+    * @param <T> Type instantiated
+    * @param clazz Class to instantiate
+    * @return New instance of clazz
+    */
+   public static <T> T newInstance(Class<T> clazz) {
+      return OBJENESIS_STD.newInstance(clazz);
+   }
+
+   /**
+    * Will create an object just like it's done by ObjectInputStream.readObject (the default
+    * constructor of the first non serializable class will be called)
+    *
+    * @param <T> Type instantiated
+    * @param clazz Class to instantiate
+    * @return New instance of clazz
+    */
+   public static <T extends Serializable> T newSerializableInstance(Class<T> clazz) {
+      return (T) OBJENESIS_SERIALIZER.newInstance(clazz);
+   }
+
+   /**
+    * Will pick the best instantiator for the provided class. If you need to create a lot of
+    * instances from the same class, it is way more efficient to create them from the same
+    * ObjectInstantiator than calling {@link #newInstance(Class)}.
+    *
+    * @param <T> Type to instantiate
+    * @param clazz Class to instantiate
+    * @return Instantiator dedicated to the class
+    */
+   public static <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) {
+      return OBJENESIS_STD.getInstantiatorOf(clazz);
+   }
+
+   /**
+    * Same as {@link #getInstantiatorOf(Class)} but providing an instantiator emulating
+    * ObjectInputStream.readObject behavior.
+    * 
+    * @see #newSerializableInstance(Class)
+    * @param <T> Type to instantiate
+    * @param clazz Class to instantiate
+    * @return Instantiator dedicated to the class
+    */
+   public static <T extends Serializable> ObjectInstantiator<T> getSerializableObjectInstantiatorOf(Class<T> clazz) {
+      return OBJENESIS_SERIALIZER.getInstantiatorOf(clazz);
+   }
+}
diff --git a/main/src/main/java/org/objenesis/ObjenesisSerializer.java b/main/src/main/java/org/objenesis/ObjenesisSerializer.java
index 8bb7e8c..be92b9d 100644
--- a/main/src/main/java/org/objenesis/ObjenesisSerializer.java
+++ b/main/src/main/java/org/objenesis/ObjenesisSerializer.java
@@ -1,43 +1,43 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis;

-

-import org.objenesis.strategy.SerializingInstantiatorStrategy;

-

-/**

- * Objenesis implementation using the {@link SerializingInstantiatorStrategy}.

- * 

- * @author Henri Tremblay

- */

-public class ObjenesisSerializer extends ObjenesisBase {

-

-   /**

-    * Default constructor using the {@link org.objenesis.strategy.SerializingInstantiatorStrategy}

-    */

-   public ObjenesisSerializer() {

-      super(new SerializingInstantiatorStrategy());

-   }

-

-   /**

-    * Instance using the {@link org.objenesis.strategy.SerializingInstantiatorStrategy} with or without caching

-    * {@link org.objenesis.instantiator.ObjectInstantiator}s

-    * 

-    * @param useCache If {@link org.objenesis.instantiator.ObjectInstantiator}s should be cached

-    */

-   public ObjenesisSerializer(boolean useCache) {

-      super(new SerializingInstantiatorStrategy(), useCache);

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import org.objenesis.strategy.SerializingInstantiatorStrategy;
+
+/**
+ * Objenesis implementation using the {@link SerializingInstantiatorStrategy}.
+ * 
+ * @author Henri Tremblay
+ */
+public class ObjenesisSerializer extends ObjenesisBase {
+
+   /**
+    * Default constructor using the {@link org.objenesis.strategy.SerializingInstantiatorStrategy}
+    */
+   public ObjenesisSerializer() {
+      super(new SerializingInstantiatorStrategy());
+   }
+
+   /**
+    * Instance using the {@link org.objenesis.strategy.SerializingInstantiatorStrategy} with or without caching
+    * {@link org.objenesis.instantiator.ObjectInstantiator}s
+    * 
+    * @param useCache If {@link org.objenesis.instantiator.ObjectInstantiator}s should be cached
+    */
+   public ObjenesisSerializer(boolean useCache) {
+      super(new SerializingInstantiatorStrategy(), useCache);
+   }
+}
diff --git a/main/src/main/java/org/objenesis/ObjenesisStd.java b/main/src/main/java/org/objenesis/ObjenesisStd.java
index 2d9b9ba..16d21c6 100644
--- a/main/src/main/java/org/objenesis/ObjenesisStd.java
+++ b/main/src/main/java/org/objenesis/ObjenesisStd.java
@@ -1,43 +1,43 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis;

-

-import org.objenesis.strategy.StdInstantiatorStrategy;

-

-/**

- * Objenesis implementation using the {@link org.objenesis.strategy.StdInstantiatorStrategy}.

- * 

- * @author Henri Tremblay

- */

-public class ObjenesisStd extends ObjenesisBase {

-

-   /**

-    * Default constructor using the {@link org.objenesis.strategy.StdInstantiatorStrategy}

-    */

-   public ObjenesisStd() {

-      super(new StdInstantiatorStrategy());

-   }

-

-   /**

-    * Instance using the {@link org.objenesis.strategy.StdInstantiatorStrategy} with or without

-    * caching {@link org.objenesis.instantiator.ObjectInstantiator}s

-    * 

-    * @param useCache If {@link org.objenesis.instantiator.ObjectInstantiator}s should be cached

-    */

-   public ObjenesisStd(boolean useCache) {

-      super(new StdInstantiatorStrategy(), useCache);

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import org.objenesis.strategy.StdInstantiatorStrategy;
+
+/**
+ * Objenesis implementation using the {@link org.objenesis.strategy.StdInstantiatorStrategy}.
+ * 
+ * @author Henri Tremblay
+ */
+public class ObjenesisStd extends ObjenesisBase {
+
+   /**
+    * Default constructor using the {@link org.objenesis.strategy.StdInstantiatorStrategy}
+    */
+   public ObjenesisStd() {
+      super(new StdInstantiatorStrategy());
+   }
+
+   /**
+    * Instance using the {@link org.objenesis.strategy.StdInstantiatorStrategy} with or without
+    * caching {@link org.objenesis.instantiator.ObjectInstantiator}s
+    * 
+    * @param useCache If {@link org.objenesis.instantiator.ObjectInstantiator}s should be cached
+    */
+   public ObjenesisStd(boolean useCache) {
+      super(new StdInstantiatorStrategy(), useCache);
+   }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/ObjectInstantiator.java b/main/src/main/java/org/objenesis/instantiator/ObjectInstantiator.java
index 47b1713..d6db8ba 100644
--- a/main/src/main/java/org/objenesis/instantiator/ObjectInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/ObjectInstantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
  * 
  * @author Leonardo Mesquita
  */
-public interface ObjectInstantiator {
+public interface ObjectInstantiator<T> {
 
    /**
     * Returns a new instance of an object. The returned object's class is defined by the
@@ -28,6 +28,6 @@
     * 
     * @return A new instance of an object.
     */
-   Object newInstance();
+   T newInstance();
 
 }
diff --git a/main/src/main/java/org/objenesis/instantiator/SerializationInstantiatorHelper.java b/main/src/main/java/org/objenesis/instantiator/SerializationInstantiatorHelper.java
index f937979..deeb54b 100644
--- a/main/src/main/java/org/objenesis/instantiator/SerializationInstantiatorHelper.java
+++ b/main/src/main/java/org/objenesis/instantiator/SerializationInstantiatorHelper.java
@@ -1,48 +1,49 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator;

-

-import java.io.Serializable;

-

-/**

- * Helper for common serialization-compatible instantiation functions

- * 

- * @author Leonardo Mesquita

- */

-public class SerializationInstantiatorHelper {

-

-   /**

-    * Returns the first non-serializable superclass of a given class. According to Java Object

-    * Serialization Specification, objects read from a stream are initialized by calling an

-    * accessible no-arg constructor from the first non-serializable superclass in the object's

-    * hierarchy, allowing the state of non-serializable fields to be correctly initialized.

-    * 

-    * @param type Serializable class for which the first non-serializable superclass is to be found

-    * @return The first non-serializable superclass of 'type'.

-    * @see java.io.Serializable

-    */

-   public static Class getNonSerializableSuperClass(Class type) {

-      Class result = type;

-      while(Serializable.class.isAssignableFrom(result)) {

-         result = result.getSuperclass();

-         if(result == null) {

-            throw new Error("Bad class hierarchy: No non-serializable parents");

-         }

-      }

-      return result;

-

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator;
+
+import java.io.Serializable;
+
+/**
+ * Helper for common serialization-compatible instantiation functions
+ * 
+ * @author Leonardo Mesquita
+ */
+public class SerializationInstantiatorHelper {
+
+   /**
+    * Returns the first non-serializable superclass of a given class. According to Java Object
+    * Serialization Specification, objects read from a stream are initialized by calling an
+    * accessible no-arg constructor from the first non-serializable superclass in the object's
+    * hierarchy, allowing the state of non-serializable fields to be correctly initialized.
+    *
+    * @param <T> Type to instantiate
+    * @param type Serializable class for which the first non-serializable superclass is to be found
+    * @return The first non-serializable superclass of 'type'.
+    * @see java.io.Serializable
+    */
+   public static <T> Class<? super T> getNonSerializableSuperClass(Class<T> type) {
+      Class<? super T> result = type;
+      while(Serializable.class.isAssignableFrom(result)) {
+         result = result.getSuperclass();
+         if(result == null) {
+            throw new Error("Bad class hierarchy: No non-serializable parents");
+         }
+      }
+      return result;
+
+   }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/android/Android10Instantiator.java b/main/src/main/java/org/objenesis/instantiator/android/Android10Instantiator.java
new file mode 100644
index 0000000..496123d
--- /dev/null
+++ b/main/src/main/java/org/objenesis/instantiator/android/Android10Instantiator.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.android;
+
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+/**
+ * Instantiator for Android API level 10 and lover which creates objects without driving their
+ * constructors, using internal methods on the Dalvik implementation of
+ * {@link java.io.ObjectInputStream}.
+ *
+ * @author Piotr 'Qertoip' WÅ‚odarek
+ */
+@Instantiator(Typology.STANDARD)
+public class Android10Instantiator<T> implements ObjectInstantiator<T> {
+   private final Class<T> type;
+   private final Method newStaticMethod;
+
+   public Android10Instantiator(Class<T> type) {
+      this.type = type;
+      newStaticMethod = getNewStaticMethod();
+   }
+
+   public T newInstance() {
+      try {
+         return type.cast(newStaticMethod.invoke(null, type, Object.class));
+      }
+      catch(Exception e) {
+         throw new ObjenesisException(e);
+      }
+   }
+
+   private static Method getNewStaticMethod() {
+      try {
+         Method newStaticMethod = ObjectInputStream.class.getDeclaredMethod(
+           "newInstance", Class.class, Class.class);
+         newStaticMethod.setAccessible(true);
+         return newStaticMethod;
+      }
+      catch(RuntimeException e) {
+         throw new ObjenesisException(e);
+      }
+      catch(NoSuchMethodException e) {
+         throw new ObjenesisException(e);
+      }
+   }
+
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/android/AndroidInstantiator.java b/main/src/main/java/org/objenesis/instantiator/android/Android17Instantiator.java
similarity index 72%
rename from main/src/main/java/org/objenesis/instantiator/android/AndroidInstantiator.java
rename to main/src/main/java/org/objenesis/instantiator/android/Android17Instantiator.java
index b3277e6..adc9b59 100644
--- a/main/src/main/java/org/objenesis/instantiator/android/AndroidInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/android/Android17Instantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,33 +15,36 @@
  */
 package org.objenesis.instantiator.android;
 
-import org.objenesis.ObjenesisException;
-import org.objenesis.instantiator.ObjectInstantiator;
-
 import java.io.ObjectStreamClass;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
 /**
- * Instantiator for Android which creates objects without driving their constructors, using internal
- * methods on the Dalvik implementation of {@link ObjectStreamClass}.
- * 
+ * Instantiator for Android API level 11 to 17 which creates objects without driving their
+ * constructors, using internal methods on the Dalvik implementation of {@link ObjectStreamClass}.
+ *
  * @author Ian Parkinson (Google Inc.)
  */
-public class AndroidInstantiator implements ObjectInstantiator {
-   private final Class type;
+@Instantiator(Typology.STANDARD)
+public class Android17Instantiator<T> implements ObjectInstantiator<T> {
+   private final Class<T> type;
    private final Method newInstanceMethod;
    private final Integer objectConstructorId;
 
-   public AndroidInstantiator(Class type) {
+   public Android17Instantiator(Class<T> type) {
       this.type = type;
       newInstanceMethod = getNewInstanceMethod();
       objectConstructorId = findConstructorIdForJavaLangObjectConstructor();
    }
 
-   public Object newInstance() {
+   public T newInstance() {
       try {
-         return newInstanceMethod.invoke(null, new Object[] {type, objectConstructorId});
+         return type.cast(newInstanceMethod.invoke(null, type, objectConstructorId));
       }
       catch(Exception e) {
          throw new ObjenesisException(e);
@@ -51,7 +54,7 @@
    private static Method getNewInstanceMethod() {
       try {
          Method newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod(
-            "newInstance", new Class[] {Class.class, Integer.TYPE});
+            "newInstance", Class.class, Integer.TYPE);
          newInstanceMethod.setAccessible(true);
          return newInstanceMethod;
       }
@@ -66,10 +69,10 @@
    private static Integer findConstructorIdForJavaLangObjectConstructor() {
       try {
          Method newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod(
-            "getConstructorId", new Class[] {Class.class});
+            "getConstructorId", Class.class);
          newInstanceMethod.setAccessible(true);
 
-         return (Integer) newInstanceMethod.invoke(null, new Object[] {Object.class});
+         return (Integer) newInstanceMethod.invoke(null, Object.class);
       }
       catch(RuntimeException e) {
          throw new ObjenesisException(e);
diff --git a/main/src/main/java/org/objenesis/instantiator/android/AndroidInstantiator.java b/main/src/main/java/org/objenesis/instantiator/android/Android18Instantiator.java
similarity index 68%
copy from main/src/main/java/org/objenesis/instantiator/android/AndroidInstantiator.java
copy to main/src/main/java/org/objenesis/instantiator/android/Android18Instantiator.java
index b3277e6..d4e280c 100644
--- a/main/src/main/java/org/objenesis/instantiator/android/AndroidInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/android/Android18Instantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,33 +15,36 @@
  */
 package org.objenesis.instantiator.android;
 
-import org.objenesis.ObjenesisException;
-import org.objenesis.instantiator.ObjectInstantiator;
-
 import java.io.ObjectStreamClass;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
-/**
- * Instantiator for Android which creates objects without driving their constructors, using internal
- * methods on the Dalvik implementation of {@link ObjectStreamClass}.
- * 
- * @author Ian Parkinson (Google Inc.)
- */
-public class AndroidInstantiator implements ObjectInstantiator {
-   private final Class type;
-   private final Method newInstanceMethod;
-   private final Integer objectConstructorId;
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
 
-   public AndroidInstantiator(Class type) {
+/**
+ * Instantiator for Android API leve 18 and higher. Same as the version 17 but the
+ * <code>newInstance</code> now takes a long in parameter
+ *
+ * @author Henri Tremblay
+ */
+@Instantiator(Typology.STANDARD)
+public class Android18Instantiator<T> implements ObjectInstantiator<T> {
+   private final Class<T> type;
+   private final Method newInstanceMethod;
+   private final Long objectConstructorId;
+
+   public Android18Instantiator(Class<T> type) {
       this.type = type;
       newInstanceMethod = getNewInstanceMethod();
       objectConstructorId = findConstructorIdForJavaLangObjectConstructor();
    }
 
-   public Object newInstance() {
+   public T newInstance() {
       try {
-         return newInstanceMethod.invoke(null, new Object[] {type, objectConstructorId});
+         return type.cast(newInstanceMethod.invoke(null, type, objectConstructorId));
       }
       catch(Exception e) {
          throw new ObjenesisException(e);
@@ -50,8 +53,8 @@
 
    private static Method getNewInstanceMethod() {
       try {
-         Method newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod(
-            "newInstance", new Class[] {Class.class, Integer.TYPE});
+         Method newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod("newInstance",
+            Class.class, Long.TYPE);
          newInstanceMethod.setAccessible(true);
          return newInstanceMethod;
       }
@@ -63,13 +66,13 @@
       }
    }
 
-   private static Integer findConstructorIdForJavaLangObjectConstructor() {
+   private static Long findConstructorIdForJavaLangObjectConstructor() {
       try {
-         Method newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod(
-            "getConstructorId", new Class[] {Class.class});
+         Method newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod("getConstructorId",
+            Class.class);
          newInstanceMethod.setAccessible(true);
 
-         return (Integer) newInstanceMethod.invoke(null, new Object[] {Object.class});
+         return (Long) newInstanceMethod.invoke(null, Object.class);
       }
       catch(RuntimeException e) {
          throw new ObjenesisException(e);
diff --git a/main/src/main/java/org/objenesis/instantiator/android/AndroidSerializationInstantiator.java b/main/src/main/java/org/objenesis/instantiator/android/AndroidSerializationInstantiator.java
index 1d9f029..6f2ab23 100644
--- a/main/src/main/java/org/objenesis/instantiator/android/AndroidSerializationInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/android/AndroidSerializationInstantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,34 +15,49 @@
  */
 package org.objenesis.instantiator.android;
 
-import org.objenesis.ObjenesisException;
-import org.objenesis.instantiator.ObjectInstantiator;
-
 import java.io.ObjectStreamClass;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
 /**
  * {@link ObjectInstantiator} for Android which creates objects using the constructor from the first
  * non-serializable parent class constructor, using internal methods on the Dalvik implementation of
  * {@link ObjectStreamClass}.
- * 
+ *
  * @author Ian Parkinson (Google Inc.)
  */
-public class AndroidSerializationInstantiator implements ObjectInstantiator {
-   private final Class type;
+@Instantiator(Typology.SERIALIZATION)
+public class AndroidSerializationInstantiator<T> implements ObjectInstantiator<T> {
+   private final Class<T> type;
    private final ObjectStreamClass objectStreamClass;
    private final Method newInstanceMethod;
 
-   public AndroidSerializationInstantiator(Class type) {
+   public AndroidSerializationInstantiator(Class<T> type) {
       this.type = type;
       newInstanceMethod = getNewInstanceMethod();
-      objectStreamClass = ObjectStreamClass.lookupAny(type);
+      Method m = null;
+      try {
+         m = ObjectStreamClass.class.getMethod("lookupAny", Class.class);
+      } catch (NoSuchMethodException e) {
+         throw new ObjenesisException(e);
+      }
+      try {
+         objectStreamClass = (ObjectStreamClass) m.invoke(null, type);
+      } catch (IllegalAccessException e) {
+         throw new ObjenesisException(e);
+      } catch (InvocationTargetException e) {
+         throw new ObjenesisException(e);
+      }
    }
 
-   public Object newInstance() {
+   public T newInstance() {
       try {
-         return newInstanceMethod.invoke(objectStreamClass, new Object[] {type});
+         return type.cast(newInstanceMethod.invoke(objectStreamClass, type));
       }
       catch(IllegalAccessException e) {
          throw new ObjenesisException(e);
@@ -58,7 +73,7 @@
    private static Method getNewInstanceMethod() {
       try {
          Method newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod(
-            "newInstance", new Class[] {Class.class});
+            "newInstance", Class.class);
          newInstanceMethod.setAccessible(true);
          return newInstanceMethod;
       }
diff --git a/main/src/main/java/org/objenesis/instantiator/annotations/Instantiator.java b/main/src/main/java/org/objenesis/instantiator/annotations/Instantiator.java
new file mode 100644
index 0000000..82186aa
--- /dev/null
+++ b/main/src/main/java/org/objenesis/instantiator/annotations/Instantiator.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Denote that the class in an instantiator of a given type
+ *
+ * @author Henri Tremblay
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Instantiator {
+
+   /**
+    * @return type of instantiator
+    */
+   Typology value();
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/annotations/Typology.java b/main/src/main/java/org/objenesis/instantiator/annotations/Typology.java
new file mode 100644
index 0000000..10682c1
--- /dev/null
+++ b/main/src/main/java/org/objenesis/instantiator/annotations/Typology.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.annotations;
+
+/**
+ * Possible types of instantiator
+ * @author Henri Tremblay
+ */
+public enum Typology {
+   /**
+    * Mark an instantiator used for standard instantiation (not calling a constructor).
+    */
+   STANDARD,
+
+   /**
+    * Mark an instantiator used for serialization.
+    */
+   SERIALIZATION,
+
+   /**
+    * Mark an instantiator that doesn't behave like a {@link #STANDARD} nor a {@link #SERIALIZATION} (e.g. calls a constructor, fails
+    * all the time, etc.)
+    */
+   NOT_COMPLIANT,
+
+   /**
+    * No type specified on the instantiator class
+    */
+   UNKNOWN
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/basic/AccessibleInstantiator.java b/main/src/main/java/org/objenesis/instantiator/basic/AccessibleInstantiator.java
index e1b96a4..e7fcb99 100644
--- a/main/src/main/java/org/objenesis/instantiator/basic/AccessibleInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/basic/AccessibleInstantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,17 +15,21 @@
  */
 package org.objenesis.instantiator.basic;
 
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
 /**
  * Instantiates a class by grabbing the no-args constructor, making it accessible and then calling
  * Constructor.newInstance(). Although this still requires no-arg constructors, it can call
  * non-public constructors (if the security manager allows it).
- * 
+ *
  * @author Joe Walnes
  * @see org.objenesis.instantiator.ObjectInstantiator
  */
-public class AccessibleInstantiator extends ConstructorInstantiator {
+@Instantiator(Typology.NOT_COMPLIANT)
+public class AccessibleInstantiator<T> extends ConstructorInstantiator<T> {
 
-   public AccessibleInstantiator(Class type) {
+   public AccessibleInstantiator(Class<T> type) {
       super(type);
       if(constructor != null) {
          constructor.setAccessible(true);
diff --git a/main/src/main/java/org/objenesis/instantiator/basic/ClassDefinitionUtils.java b/main/src/main/java/org/objenesis/instantiator/basic/ClassDefinitionUtils.java
new file mode 100644
index 0000000..1f83a29
--- /dev/null
+++ b/main/src/main/java/org/objenesis/instantiator/basic/ClassDefinitionUtils.java
@@ -0,0 +1,230 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.basic;
+
+/*
+ * Copyright 2003,2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.objenesis.ObjenesisException;
+
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+
+/**
+ * Helper class for ProxyObjectInstantiator. We can see the details of a class specification
+ * <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html">here</a>
+ *
+ * @author Henri Tremblay
+ */
+public final class ClassDefinitionUtils {
+
+   public static final byte OPS_aload_0 = 42;
+   public static final byte OPS_invokespecial = -73; // has two bytes parameters
+   public static final byte OPS_return = -79;
+   public static final byte OPS_new = -69;
+   public static final byte OPS_dup = 89;
+   public static final byte OPS_areturn = -80;
+
+   public static final int CONSTANT_Utf8 = 1;
+   public static final int CONSTANT_Integer = 3;
+   public static final int CONSTANT_Float = 4;
+   public static final int CONSTANT_Long = 5;
+   public static final int CONSTANT_Double = 6;
+   public static final int CONSTANT_Class = 7;
+   public static final int CONSTANT_String = 8;
+   public static final int CONSTANT_Fieldref = 9;
+   public static final int CONSTANT_Methodref = 10;
+   public static final int CONSTANT_InterfaceMethodref = 11;
+   public static final int CONSTANT_NameAndType = 12;
+   public static final int CONSTANT_MethodHandle = 15;
+   public static final int CONSTANT_MethodType = 16;
+   public static final int CONSTANT_InvokeDynamic = 18;
+
+   public static final int ACC_PUBLIC = 0x0001; // Declared public; may be accessed from outside its package.
+   public static final int ACC_FINAL = 0x0010; // Declared final; no subclasses allowed.
+   public static final int ACC_SUPER = 0x0020; // Treat superclass methods specially when invoked by the invokespecial instruction.
+   public static final int ACC_INTERFACE = 0x0200; // Is an interface, not a class.
+   public static final int ACC_ABSTRACT = 0x0400; // Declared abstract; must not be instantiated.
+   public static final int ACC_SYNTHETIC = 0x1000; // Declared synthetic; not present in the source code.
+   public static final int ACC_ANNOTATION = 0x2000; // Declared as an annotation type.
+   public static final int ACC_ENUM = 0x4000; // Declared as an enum type.
+
+   public static final byte[] MAGIC = { (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe };
+   public static final byte[] VERSION = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x31 }; // minor_version, major_version (Java 5)
+
+   private ClassDefinitionUtils() { }
+
+   private static Method DEFINE_CLASS;
+   private static final ProtectionDomain PROTECTION_DOMAIN;
+
+   static {
+      PROTECTION_DOMAIN = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
+         public ProtectionDomain run() {
+            return ClassDefinitionUtils.class.getProtectionDomain();
+         }
+      });
+
+      AccessController.doPrivileged(new PrivilegedAction<Object>() {
+         public Object run() {
+            try {
+               Class<?> loader = Class.forName("java.lang.ClassLoader"); // JVM crash w/o this
+               DEFINE_CLASS = loader.getDeclaredMethod("defineClass",
+                  new Class[]{ String.class,
+                     byte[].class,
+                     Integer.TYPE,
+                     Integer.TYPE,
+                     ProtectionDomain.class });
+               DEFINE_CLASS.setAccessible(true);
+            } catch (ClassNotFoundException e) {
+               throw new ObjenesisException(e);
+            } catch (NoSuchMethodException e) {
+               throw new ObjenesisException(e);
+            }
+            return null;
+         }
+      });
+   }
+
+   /**
+    * Define a class in the provided class loader from the array of bytes. Inspired by cglib
+    * <code>ReflectUtils.defineClass</code>
+    *
+    * @param <T> type of the class returned
+    * @param className class name in the format <code>org.objenesis.MyClass</code>
+    * @param b bytes representing the class
+    * @param loader the class loader where the class will be loaded
+    * @return the newly loaded class
+    * @throws Exception whenever something goes wrong
+    */
+   @SuppressWarnings("unchecked")
+   public static <T> Class<T> defineClass(String className, byte[] b, ClassLoader loader)
+      throws Exception {
+      Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), PROTECTION_DOMAIN };
+      Class<T> c = (Class<T>) DEFINE_CLASS.invoke(loader, args);
+      // Force static initializers to run.
+      Class.forName(className, true, loader);
+      return c;
+   }
+
+   /**
+    * Read the bytes of a class from the classpath
+    *
+    * @param className full class name including the package
+    * @return the bytes representing the class
+    * @throws IllegalArgumentException if the class is longer than 2500 bytes
+    * @throws IOException if we fail to read the class
+    */
+   public static byte[] readClass(String className) throws IOException {
+      // convert to a resource
+      className = classNameToResource(className);
+
+      byte[] b = new byte[2500]; // I'm assuming that I'm reading class that are not too big
+
+      int length;
+
+      InputStream in = ClassDefinitionUtils.class.getClassLoader().getResourceAsStream(className);
+      try {
+         length = in.read(b);
+      }
+      finally {
+         in.close();
+      }
+
+      if(length >= 2500) {
+         throw new IllegalArgumentException("The class is longer that 2500 bytes which is currently unsupported");
+      }
+
+      byte[] copy = new byte[length];
+      System.arraycopy(b, 0, copy, 0, length);
+      return copy;
+   }
+
+   /**
+    * Write all class bytes to a file.
+    *
+    * @param fileName file where the bytes will be written
+    * @param bytes bytes representing the class
+    * @throws IOException if we fail to write the class
+    */
+   public static void writeClass(String fileName, byte[] bytes) throws IOException {
+      BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName));
+      try {
+         out.write(bytes);
+      }
+      finally {
+         out.close();
+      }
+   }
+
+   /**
+    * Will convert a class name to its name in the class definition format (e.g {@code org.objenesis.EmptyClass}
+    * becomes {@code org/objenesis/EmptyClass})
+    *
+    * @param className full class name including the package
+    * @return the internal name
+    */
+   public static String classNameToInternalClassName(String className) {
+      return className.replace('.', '/');
+   }
+
+   /**
+    * Will convert a class name to its class loader resource name (e.g {@code org.objenesis.EmptyClass}
+    * becomes {@code org/objenesis/EmptyClass.class})
+    *
+    * @param className full class name including the package
+    * @return the resource name
+    */
+   public static String classNameToResource(String className) {
+      return classNameToInternalClassName(className) + ".class";
+   }
+
+   /**
+    * Check if this class already exists in the class loader and return it if it does
+    *
+    * @param <T> type of the class returned
+    * @param classLoader Class loader where to search the class
+    * @param className Class name with full path
+    * @return the class if it already exists or null
+    */
+   @SuppressWarnings("unchecked")
+   public static <T> Class<T> getExistingClass(ClassLoader classLoader, String className) {
+      try {
+         return (Class<T>) Class.forName(className, true, classLoader);
+      }
+      catch (ClassNotFoundException e) {
+         return null;
+      }
+   }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/basic/ConstructorInstantiator.java b/main/src/main/java/org/objenesis/instantiator/basic/ConstructorInstantiator.java
index 7db10f5..b2b6ad2 100644
--- a/main/src/main/java/org/objenesis/instantiator/basic/ConstructorInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/basic/ConstructorInstantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,19 +19,23 @@
 
 import org.objenesis.ObjenesisException;
 import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
 
 /**
  * Instantiates a class by grabbing the no args constructor and calling Constructor.newInstance().
  * This can deal with default public constructors, but that's about it.
- * 
+ *
  * @author Joe Walnes
+ * @param <T> Type instantiated
  * @see ObjectInstantiator
  */
-public class ConstructorInstantiator implements ObjectInstantiator {
+@Instantiator(Typology.NOT_COMPLIANT)
+public class ConstructorInstantiator<T> implements ObjectInstantiator<T> {
 
-   protected Constructor constructor;
+   protected Constructor<T> constructor;
 
-   public ConstructorInstantiator(Class type) {
+   public ConstructorInstantiator(Class<T> type) {
       try {
          constructor = type.getDeclaredConstructor((Class[]) null);
       }
@@ -40,7 +44,7 @@
       }
    }
 
-   public Object newInstance() {
+   public T newInstance() {
       try {
          return constructor.newInstance((Object[]) null);
       }
diff --git a/main/src/main/java/org/objenesis/instantiator/basic/FailingInstantiator.java b/main/src/main/java/org/objenesis/instantiator/basic/FailingInstantiator.java
new file mode 100644
index 0000000..b620642
--- /dev/null
+++ b/main/src/main/java/org/objenesis/instantiator/basic/FailingInstantiator.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.basic;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+/**
+ * The instantiator that always throws an exception. Mainly used for tests
+ *
+ * @author Henri Tremblay
+ */
+@Instantiator(Typology.NOT_COMPLIANT)
+public class FailingInstantiator<T> implements ObjectInstantiator<T> {
+
+   public FailingInstantiator(Class<T> type) {
+   }
+
+   /**
+    * @return Always throwing an exception
+    */
+   public T newInstance() {
+      throw new ObjenesisException("Always failing");
+   }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/basic/NewInstanceInstantiator.java b/main/src/main/java/org/objenesis/instantiator/basic/NewInstanceInstantiator.java
index e95f0f8..4080839 100644
--- a/main/src/main/java/org/objenesis/instantiator/basic/NewInstanceInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/basic/NewInstanceInstantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,26 +17,29 @@
 
 import org.objenesis.ObjenesisException;
 import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
 
 /**
  * The simplest instantiator - simply calls Class.newInstance(). This can deal with default public
  * constructors, but that's about it.
- * 
+ *
  * @author Joe Walnes
  * @see ObjectInstantiator
  */
-public class NewInstanceInstantiator implements ObjectInstantiator {
+@Instantiator(Typology.NOT_COMPLIANT)
+public class NewInstanceInstantiator<T> implements ObjectInstantiator<T> {
 
-   private final Class type;
+   private final Class<T> type;
 
-   public NewInstanceInstantiator(Class type) {
+   public NewInstanceInstantiator(Class<T> type) {
       this.type = type;
    }
 
-   public Object newInstance() {
+   public T newInstance() {
       try {
          return type.newInstance();
-      }      
+      }
       catch(Exception e) {
          throw new ObjenesisException(e);
       }
diff --git a/main/src/main/java/org/objenesis/instantiator/NullInstantiator.java b/main/src/main/java/org/objenesis/instantiator/basic/NullInstantiator.java
similarity index 61%
copy from main/src/main/java/org/objenesis/instantiator/NullInstantiator.java
copy to main/src/main/java/org/objenesis/instantiator/basic/NullInstantiator.java
index ab2a44f..1429118 100644
--- a/main/src/main/java/org/objenesis/instantiator/NullInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/basic/NullInstantiator.java
@@ -1,31 +1,39 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator;

-

-/**

- * The instantiator that always return a null instance

- * 

- * @author Henri Tremblay

- */

-public class NullInstantiator implements ObjectInstantiator {

-

-   /**

-    * @return Always null

-    */

-   public Object newInstance() {

-      return null;

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.basic;
+
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+/**
+ * The instantiator that always return a null instance
+ *
+ * @author Henri Tremblay
+ */
+@Instantiator(Typology.NOT_COMPLIANT)
+public class NullInstantiator<T> implements ObjectInstantiator<T> {
+
+   public NullInstantiator(Class<T> type) {
+   }
+
+   /**
+    * @return Always null
+    */
+   public T newInstance() {
+      return null;
+   }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/basic/ObjectInputStreamInstantiator.java b/main/src/main/java/org/objenesis/instantiator/basic/ObjectInputStreamInstantiator.java
index 265f813..cf598d4 100644
--- a/main/src/main/java/org/objenesis/instantiator/basic/ObjectInputStreamInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/basic/ObjectInputStreamInstantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,8 @@
 
 import org.objenesis.ObjenesisException;
 import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
 
 /**
  * Instantiates a class by using a dummy input stream that always feeds data for an empty object of
@@ -34,11 +36,12 @@
  * defines a "readResolve" method, since it may return objects that have been returned previously
  * (i.e., there's no guarantee that the returned object is a new one), or even objects from a
  * completely different class.
- * 
+ *
  * @author Leonardo Mesquita
  * @see org.objenesis.instantiator.ObjectInstantiator
  */
-public class ObjectInputStreamInstantiator implements ObjectInstantiator {
+@Instantiator(Typology.SERIALIZATION)
+public class ObjectInputStreamInstantiator<T> implements ObjectInstantiator<T> {
    private static class MockStream extends InputStream {
 
       private int pointer;
@@ -77,7 +80,7 @@
 
       }
 
-      public MockStream(Class clazz) {
+      public MockStream(Class<?> clazz) {
          this.pointer = 0;
          this.sequence = 0;
          this.data = HEADER;
@@ -116,6 +119,7 @@
          data = buffers[sequence];
       }
 
+      @Override
       public int read() throws IOException {
          int result = data[pointer++];
          if(pointer >= data.length) {
@@ -125,10 +129,12 @@
          return result;
       }
 
+      @Override
       public int available() throws IOException {
          return Integer.MAX_VALUE;
       }
 
+      @Override
       public int read(byte[] b, int off, int len) throws IOException {
          int left = len;
          int remaining = data.length - pointer;
@@ -151,7 +157,7 @@
 
    private ObjectInputStream inputStream;
 
-   public ObjectInputStreamInstantiator(Class clazz) {
+   public ObjectInputStreamInstantiator(Class<T> clazz) {
       if(Serializable.class.isAssignableFrom(clazz)) {
          try {
             this.inputStream = new ObjectInputStream(new MockStream(clazz));
@@ -161,14 +167,15 @@
          }
       }
       else {
-    	  throw new ObjenesisException(new NotSerializableException(clazz+" not serializable"));
+         throw new ObjenesisException(new NotSerializableException(clazz + " not serializable"));
       }
    }
 
-   public Object newInstance() {
+   @SuppressWarnings("unchecked")
+   public T newInstance() {
       try {
-         return inputStream.readObject();
-      }      
+         return (T) inputStream.readObject();
+      }
       catch(ClassNotFoundException e) {
          throw new Error("ClassNotFoundException: " + e.getMessage());
       }
diff --git a/main/src/main/java/org/objenesis/instantiator/basic/ObjectStreamClassInstantiator.java b/main/src/main/java/org/objenesis/instantiator/basic/ObjectStreamClassInstantiator.java
index 742ec5a..7aac1df 100644
--- a/main/src/main/java/org/objenesis/instantiator/basic/ObjectStreamClassInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/basic/ObjectStreamClassInstantiator.java
@@ -1,72 +1,75 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator.basic;

-

-import java.io.ObjectStreamClass;

-import java.lang.reflect.Method;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Instantiates a class by using reflection to make a call to private method

- * ObjectStreamClass.newInstance, present in many JVM implementations. This instantiator will create

- * classes in a way compatible with serialization, calling the first non-serializable superclass'

- * no-arg constructor.

- * 

- * @author Leonardo Mesquita

- * @see ObjectInstantiator

- * @see java.io.Serializable

- */

-public class ObjectStreamClassInstantiator implements ObjectInstantiator {

-

-   private static Method newInstanceMethod;

-

-   private static void initialize() {

-      if(newInstanceMethod == null) {

-         try {

-            newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod("newInstance",

-               new Class[] {});

-            newInstanceMethod.setAccessible(true);

-         }

-         catch(RuntimeException e) {

-            throw new ObjenesisException(e);

-         }

-         catch(NoSuchMethodException e) {

-            throw new ObjenesisException(e);

-         }         

-      }

-   }

-

-   private final ObjectStreamClass objStreamClass;

-

-   public ObjectStreamClassInstantiator(Class type) {

-      initialize();

-      objStreamClass = ObjectStreamClass.lookup(type);

-   }

-

-   public Object newInstance() {

-	   

-      try {

-         return newInstanceMethod.invoke(objStreamClass, new Object[] {});

-      }

-      catch(Exception e) {

-         throw new ObjenesisException(e);

-      }

-      

-   }

-

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.basic;
+
+import java.io.ObjectStreamClass;
+import java.lang.reflect.Method;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+/**
+ * Instantiates a class by using reflection to make a call to private method
+ * ObjectStreamClass.newInstance, present in many JVM implementations. This instantiator will create
+ * classes in a way compatible with serialization, calling the first non-serializable superclass'
+ * no-arg constructor.
+ *
+ * @author Leonardo Mesquita
+ * @see ObjectInstantiator
+ * @see java.io.Serializable
+ */
+@Instantiator(Typology.SERIALIZATION)
+public class ObjectStreamClassInstantiator<T> implements ObjectInstantiator<T> {
+
+   private static Method newInstanceMethod;
+
+   private static void initialize() {
+      if(newInstanceMethod == null) {
+         try {
+            newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod("newInstance");
+            newInstanceMethod.setAccessible(true);
+         }
+         catch(RuntimeException e) {
+            throw new ObjenesisException(e);
+         }
+         catch(NoSuchMethodException e) {
+            throw new ObjenesisException(e);
+         }
+      }
+   }
+
+   private final ObjectStreamClass objStreamClass;
+
+   public ObjectStreamClassInstantiator(Class<T> type) {
+      initialize();
+      objStreamClass = ObjectStreamClass.lookup(type);
+   }
+
+   @SuppressWarnings("unchecked")
+   public T newInstance() {
+
+      try {
+         return (T) newInstanceMethod.invoke(objStreamClass);
+      }
+      catch(Exception e) {
+         throw new ObjenesisException(e);
+      }
+
+   }
+
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/basic/ProxyingInstantiator.java b/main/src/main/java/org/objenesis/instantiator/basic/ProxyingInstantiator.java
new file mode 100644
index 0000000..e97558c
--- /dev/null
+++ b/main/src/main/java/org/objenesis/instantiator/basic/ProxyingInstantiator.java
@@ -0,0 +1,192 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.basic;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import static org.objenesis.instantiator.basic.ClassDefinitionUtils.*;
+
+/**
+ * This instantiator creates a class by dynamically extending it. It will skip the call to the parent constructor
+ * in the bytecode. So that the constructor is indeed not called but you however instantiate a child class, not
+ * the actual class. The class loader will normally throw a {@code VerifyError} is you do that. However, using
+ * {@code -Xverify:none} shoud make it work
+ *
+ * @author Henri Tremblay
+ */
+@Instantiator(Typology.STANDARD)
+public class ProxyingInstantiator<T> implements ObjectInstantiator<T> {
+
+   private static final int INDEX_CLASS_THIS = 1;
+   private static final int INDEX_CLASS_SUPERCLASS = 2;
+   private static final int INDEX_UTF8_CONSTRUCTOR_NAME = 3;
+   private static final int INDEX_UTF8_CONSTRUCTOR_DESC = 4;
+   private static final int INDEX_UTF8_CODE_ATTRIBUTE = 5;
+   private static final int INDEX_UTF8_CLASS = 7;
+   private static final int INDEX_UTF8_SUPERCLASS = 8;
+
+   private static int CONSTANT_POOL_COUNT = 9;
+
+   private static final byte[] CODE = { OPS_aload_0, OPS_return};
+   private static final int CODE_ATTRIBUTE_LENGTH = 12 + CODE.length;
+
+   private static final String SUFFIX = "$$$Objenesis";
+
+   private static final String CONSTRUCTOR_NAME = "<init>";
+   private static final String CONSTRUCTOR_DESC = "()V";
+
+   private final Class<?> newType;
+
+   public ProxyingInstantiator(Class<T> type) {
+
+      byte[] classBytes = writeExtendingClass(type, SUFFIX);
+
+      try {
+         newType = ClassDefinitionUtils.defineClass(type.getName() + SUFFIX, classBytes, type.getClassLoader());
+      } catch (Exception e) {
+         throw new ObjenesisException(e);
+      }
+   }
+
+   @SuppressWarnings("unchecked")
+   public T newInstance() {
+      try {
+         return (T) newType.newInstance();
+      } catch (InstantiationException e) {
+         throw new ObjenesisException(e);
+      } catch (IllegalAccessException e) {
+         throw new ObjenesisException(e);
+      }
+   }
+
+   /**
+    * Will generate the bytes for a class extending the type passed in parameter. This class will
+    * only have an empty default constructor
+    *
+    * @param type type to extend
+    * @param suffix the suffix appended to the class name to create the next extending class name
+    * @return the byte for the class
+    * @throws ObjenesisException is something goes wrong
+    */
+   private static byte[] writeExtendingClass(Class<?> type, String suffix) {
+      String parentClazz = classNameToInternalClassName(type.getName());
+      String clazz = parentClazz + suffix;
+
+      DataOutputStream in = null;
+      ByteArrayOutputStream bIn = new ByteArrayOutputStream(1000); // 1000 should be large enough to fit the entire class
+      try {
+         in = new DataOutputStream(bIn);
+
+         in.write(MAGIC);
+         in.write(VERSION);
+         in.writeShort(CONSTANT_POOL_COUNT);
+
+         // set all the constant pool here
+
+         // 1. class
+         in.writeByte(CONSTANT_Class);
+         in.writeShort(INDEX_UTF8_CLASS);
+
+         // 2. super class
+         in.writeByte(CONSTANT_Class);
+         in.writeShort(INDEX_UTF8_SUPERCLASS);
+
+         // 3. default constructor name
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF(CONSTRUCTOR_NAME);
+
+         // 4. default constructor description
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF(CONSTRUCTOR_DESC);
+
+         // 5. Code
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF("Code");
+
+         // 6. Class name
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF("L" + clazz + ";");
+
+         // 7. Class name (again)
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF(clazz);
+
+         // 8. Superclass name
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF(parentClazz);
+
+         // end of constant pool
+
+         // access flags: We want public, ACC_SUPER is always there
+         in.writeShort(ACC_PUBLIC | ACC_SUPER);
+
+         // this class index in the constant pool
+         in.writeShort(INDEX_CLASS_THIS);
+
+         // super class index in the constant pool
+         in.writeShort(INDEX_CLASS_SUPERCLASS);
+
+         // interfaces implemented count (we have none)
+         in.writeShort(0);
+
+         // fields count (we have none)
+         in.writeShort(0);
+
+         // methods count (we have one: the default constructor)
+         in.writeShort(1);
+
+         // default constructor method_info
+         in.writeShort(ACC_PUBLIC);
+         in.writeShort(INDEX_UTF8_CONSTRUCTOR_NAME); // index of the method name (<init>)
+         in.writeShort(INDEX_UTF8_CONSTRUCTOR_DESC); // index of the description
+         in.writeShort(1); // number of attributes: only one, the code
+
+         // code attribute of the default constructor
+         in.writeShort(INDEX_UTF8_CODE_ATTRIBUTE);
+         in.writeInt(CODE_ATTRIBUTE_LENGTH); // attribute length
+         in.writeShort(1); // max_stack
+         in.writeShort(1); // max_locals
+         in.writeInt(CODE.length); // code length
+         in.write(CODE);
+         in.writeShort(0); // exception_table_length = 0
+         in.writeShort(0); // attributes count = 0, no need to have LineNumberTable and LocalVariableTable
+
+         // class attributes
+         in.writeShort(0); // none. No need to have a source file attribute
+
+
+      } catch (IOException e) {
+         throw new ObjenesisException(e);
+      } finally {
+         if(in != null) {
+            try {
+               in.close();
+            } catch (IOException e) {
+               throw new ObjenesisException(e);
+            }
+         }
+      }
+
+      return bIn.toByteArray();
+   }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/gcj/GCJInstantiator.java b/main/src/main/java/org/objenesis/instantiator/gcj/GCJInstantiator.java
index e1180dc..08c9bc6 100644
--- a/main/src/main/java/org/objenesis/instantiator/gcj/GCJInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/gcj/GCJInstantiator.java
@@ -1,48 +1,52 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator.gcj;

-

-import java.lang.reflect.InvocationTargetException;

-

-import org.objenesis.ObjenesisException;

-

-/**

- * Instantiates a class by making a call to internal GCJ private methods. It is only supposed to

- * work on GCJ JVMs. This instantiator will not call any constructors.

- * 

- * @author Leonardo Mesquita

- * @see org.objenesis.instantiator.ObjectInstantiator

- */

-public class GCJInstantiator extends GCJInstantiatorBase {

-   public GCJInstantiator(Class type) {

-      super(type);

-   }

-

-   public Object newInstance() {

-      try {

-         return newObjectMethod.invoke(dummyStream, new Object[] {type, Object.class});

-      }

-      catch(RuntimeException e) {

-         throw new ObjenesisException(e);

-      }

-      catch(IllegalAccessException e) {

-         throw new ObjenesisException(e);

-      }

-      catch(InvocationTargetException e) {

-         throw new ObjenesisException(e);

-      }

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.gcj;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+/**
+ * Instantiates a class by making a call to internal GCJ private methods. It is only supposed to
+ * work on GCJ JVMs. This instantiator will not call any constructors.
+ *
+ * @author Leonardo Mesquita
+ * @see org.objenesis.instantiator.ObjectInstantiator
+ */
+@Instantiator(Typology.STANDARD)
+public class GCJInstantiator<T> extends GCJInstantiatorBase<T> {
+   public GCJInstantiator(Class<T> type) {
+      super(type);
+   }
+
+   @Override
+   public T newInstance() {
+      try {
+         return type.cast(newObjectMethod.invoke(dummyStream, type, Object.class));
+      }
+      catch(RuntimeException e) {
+         throw new ObjenesisException(e);
+      }
+      catch(IllegalAccessException e) {
+         throw new ObjenesisException(e);
+      }
+      catch(InvocationTargetException e) {
+         throw new ObjenesisException(e);
+      }
+   }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/gcj/GCJInstantiatorBase.java b/main/src/main/java/org/objenesis/instantiator/gcj/GCJInstantiatorBase.java
index 13bfc90..4477672 100644
--- a/main/src/main/java/org/objenesis/instantiator/gcj/GCJInstantiatorBase.java
+++ b/main/src/main/java/org/objenesis/instantiator/gcj/GCJInstantiatorBase.java
@@ -1,69 +1,69 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator.gcj;

-

-import java.io.IOException;

-import java.io.ObjectInputStream;

-import java.lang.reflect.Method;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Base class for GCJ-based instantiators. It initializes reflection access to method

- * ObjectInputStream.newObject, as well as creating a dummy ObjectInputStream to be used as the

- * "this" argument for the method.

- * 

- * @author Leonardo Mesquita

- */

-public abstract class GCJInstantiatorBase implements ObjectInstantiator {

-   static Method newObjectMethod = null;

-   static ObjectInputStream dummyStream;

-

-   private static class DummyStream extends ObjectInputStream {

-      public DummyStream() throws IOException {

-      }

-   }

-

-   private static void initialize() {

-      if(newObjectMethod == null) {

-         try {

-            newObjectMethod = ObjectInputStream.class.getDeclaredMethod("newObject", new Class[] {

-               Class.class, Class.class});

-            newObjectMethod.setAccessible(true);

-            dummyStream = new DummyStream();

-         }

-         catch(RuntimeException e) {

-            throw new ObjenesisException(e);

-         }

-         catch(NoSuchMethodException e) {

-            throw new ObjenesisException(e);

-         }

-         catch(IOException e) {

-            throw new ObjenesisException(e);

-         }

-      }

-   }

-

-   protected final Class type;

-

-   public GCJInstantiatorBase(Class type) {

-      this.type = type;

-      initialize();

-   }

-

-   public abstract Object newInstance();

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.gcj;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Base class for GCJ-based instantiators. It initializes reflection access to method
+ * ObjectInputStream.newObject, as well as creating a dummy ObjectInputStream to be used as the
+ * "this" argument for the method.
+ * 
+ * @author Leonardo Mesquita
+ */
+public abstract class GCJInstantiatorBase<T> implements ObjectInstantiator<T> {
+   static Method newObjectMethod = null;
+   static ObjectInputStream dummyStream;
+
+   private static class DummyStream extends ObjectInputStream {
+      public DummyStream() throws IOException {
+      }
+   }
+
+   private static void initialize() {
+      if(newObjectMethod == null) {
+         try {
+            newObjectMethod = ObjectInputStream.class.getDeclaredMethod("newObject", new Class[] {
+               Class.class, Class.class});
+            newObjectMethod.setAccessible(true);
+            dummyStream = new DummyStream();
+         }
+         catch(RuntimeException e) {
+            throw new ObjenesisException(e);
+         }
+         catch(NoSuchMethodException e) {
+            throw new ObjenesisException(e);
+         }
+         catch(IOException e) {
+            throw new ObjenesisException(e);
+         }
+      }
+   }
+
+   protected final Class<T> type;
+
+   public GCJInstantiatorBase(Class<T> type) {
+      this.type = type;
+      initialize();
+   }
+
+   public abstract T newInstance();
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/gcj/GCJSerializationInstantiator.java b/main/src/main/java/org/objenesis/instantiator/gcj/GCJSerializationInstantiator.java
index e2c1609..c6a4cd6 100644
--- a/main/src/main/java/org/objenesis/instantiator/gcj/GCJSerializationInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/gcj/GCJSerializationInstantiator.java
@@ -1,46 +1,50 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator.gcj;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.SerializationInstantiatorHelper;

-

-/**

- * Instantiates a class by making a call to internal GCJ private methods. It is only supposed to

- * work on GCJ JVMs. This instantiator will create classes in a way compatible with serialization,

- * calling the first non-serializable superclass' no-arg constructor.

- * 

- * @author Leonardo Mesquita

- * @see org.objenesis.instantiator.ObjectInstantiator

- */

-public class GCJSerializationInstantiator extends GCJInstantiatorBase {

-   private Class superType;

-

-   public GCJSerializationInstantiator(Class type) {

-      super(type);

-      this.superType = SerializationInstantiatorHelper.getNonSerializableSuperClass(type);

-   }

-

-   public Object newInstance() {

-      try {

-         return newObjectMethod.invoke(dummyStream, new Object[] {type, superType});

-      }

-      catch(Exception e) {

-         throw new ObjenesisException(e);

-      }

-   }

-

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.gcj;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.SerializationInstantiatorHelper;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+/**
+ * Instantiates a class by making a call to internal GCJ private methods. It is only supposed to
+ * work on GCJ JVMs. This instantiator will create classes in a way compatible with serialization,
+ * calling the first non-serializable superclass' no-arg constructor.
+ *
+ * @author Leonardo Mesquita
+ * @see org.objenesis.instantiator.ObjectInstantiator
+ */
+@Instantiator(Typology.SERIALIZATION)
+public class GCJSerializationInstantiator<T> extends GCJInstantiatorBase<T> {
+   private Class<? super T> superType;
+
+   public GCJSerializationInstantiator(Class<T> type) {
+      super(type);
+      this.superType = SerializationInstantiatorHelper.getNonSerializableSuperClass(type);
+   }
+
+   @Override
+   public T newInstance() {
+      try {
+         return type.cast(newObjectMethod.invoke(dummyStream, type, superType));
+      }
+      catch(Exception e) {
+         throw new ObjenesisException(e);
+      }
+   }
+
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/jrockit/JRockit131Instantiator.java b/main/src/main/java/org/objenesis/instantiator/jrockit/JRockit131Instantiator.java
deleted file mode 100644
index 7db9652..0000000
--- a/main/src/main/java/org/objenesis/instantiator/jrockit/JRockit131Instantiator.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/**

- * COPYRIGHT & LICENSE

- *

- * This code is Copyright (c) 2006 BEA Systems, inc. It is provided free, as-is and without any warranties for the purpose of

- * inclusion in Objenesis or any other open source project with a FSF approved license, as long as this notice is not

- * removed. There are no limitations on modifying or repackaging the code apart from this. 

- *

- * BEA does not guarantee that the code works, and provides no support for it. Use at your own risk.

- *

- * Originally developed by Leonardo Mesquita. Copyright notice added by Henrik Ståhl, BEA JRockit Product Manager.

- *  

- */

-package org.objenesis.instantiator.jrockit;

-

-import java.lang.reflect.Constructor;

-import java.lang.reflect.Method;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Instantiates a class by making a call to internal JRockit private methods. It is only supposed to

- * work on JRockit 7.0 JVMs, which are compatible with Java API 1.3.1. This instantiator will not

- * call any constructors.

- * 

- * @author Leonardo Mesquita

- * @see org.objenesis.instantiator.ObjectInstantiator

- */

-public class JRockit131Instantiator implements ObjectInstantiator {

-

-   private Constructor mungedConstructor;

-

-   private static Method newConstructorForSerializationMethod;

-

-   private static void initialize() {

-      if(newConstructorForSerializationMethod == null) {

-         Class cl;

-         try {

-            cl = Class.forName("COM.jrockit.reflect.MemberAccess");

-            newConstructorForSerializationMethod = cl.getDeclaredMethod(

-               "newConstructorForSerialization", new Class[] {Constructor.class, Class.class});

-            newConstructorForSerializationMethod.setAccessible(true);

-         }

-         catch(RuntimeException e) {

-            throw new ObjenesisException(e);

-         }

-         catch(ClassNotFoundException e) {

-            throw new ObjenesisException(e);

-         }

-         catch(NoSuchMethodException e) {

-            throw new ObjenesisException(e);

-         }

-      }

-   }

-

-   public JRockit131Instantiator(Class type) {

-      initialize();

-

-      if(newConstructorForSerializationMethod != null) {

-

-         Constructor javaLangObjectConstructor;

-

-         try {

-            javaLangObjectConstructor = Object.class.getConstructor((Class[]) null);

-         }

-         catch(NoSuchMethodException e) {

-            throw new Error("Cannot find constructor for java.lang.Object!");

-         }

-

-         try {

-            mungedConstructor = (Constructor) newConstructorForSerializationMethod.invoke(null,

-               new Object[] {javaLangObjectConstructor, type});

-         }

-         catch(Exception e) {

-        	 throw new ObjenesisException(e);

-         }

-      }

-

-   }

-

-   public Object newInstance() {

-      try {

-         return mungedConstructor.newInstance((Object[]) null);

-      }

-      catch(Exception e) {

-         throw new ObjenesisException(e);

-      }

-   }

-}

diff --git a/main/src/main/java/org/objenesis/instantiator/jrockit/JRockitLegacyInstantiator.java b/main/src/main/java/org/objenesis/instantiator/jrockit/JRockitLegacyInstantiator.java
deleted file mode 100644
index 9050353..0000000
--- a/main/src/main/java/org/objenesis/instantiator/jrockit/JRockitLegacyInstantiator.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/**

- * COPYRIGHT & LICENSE

- *

- * This code is Copyright (c) 2006 BEA Systems, inc. It is provided free, as-is and without any warranties for the purpose of

- * inclusion in Objenesis or any other open source project with a FSF approved license, as long as this notice is not

- * removed. There are no limitations on modifying or repackaging the code apart from this. 

- *

- * BEA does not guarantee that the code works, and provides no support for it. Use at your own risk.

- *

- * Originally developed by Leonardo Mesquita. Copyright notice added by Henrik Ståhl, BEA JRockit Product Manager.

- *  

- */

-

-package org.objenesis.instantiator.jrockit;

-

-import java.lang.reflect.Method;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Instantiates a class by making a call to internal JRockit private methods. It is only supposed to

- * work on JRockit 1.4.2 JVMs prior to release R25.1. From release R25.1 on, JRockit supports

- * sun.reflect.ReflectionFactory, making this "trick" unnecessary. This instantiator will not call

- * any constructors.

- * 

- * @author Leonardo Mesquita

- * @see org.objenesis.instantiator.ObjectInstantiator

- * @see org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator

- */

-public class JRockitLegacyInstantiator implements ObjectInstantiator {

-   private static Method safeAllocObjectMethod = null;

-

-   private static void initialize() {

-      if(safeAllocObjectMethod == null) {

-         Class memSystem;

-         try {

-            memSystem = Class.forName("jrockit.vm.MemSystem");

-            safeAllocObjectMethod = memSystem.getDeclaredMethod("safeAllocObject",

-               new Class[] {Class.class});

-            safeAllocObjectMethod.setAccessible(true);

-         }

-         catch(RuntimeException e) {

-            throw new ObjenesisException(e);

-         }

-         catch(ClassNotFoundException e) {

-            throw new ObjenesisException(e);

-         }

-         catch(NoSuchMethodException e) {

-            throw new ObjenesisException(e);

-         }

-      }

-   }

-

-   private final Class type;

-

-   public JRockitLegacyInstantiator(Class type) {

-      initialize();

-      this.type = type;

-   }

-

-   public Object newInstance() {      

-      try {

-         return safeAllocObjectMethod.invoke(null, new Object[] {type});

-      }

-      catch(Exception e) {

-         throw new ObjenesisException(e);

-      }

-   }

-}

diff --git a/main/src/main/java/org/objenesis/instantiator/perc/PercInstantiator.java b/main/src/main/java/org/objenesis/instantiator/perc/PercInstantiator.java
index 9777fcc..7a2f579 100644
--- a/main/src/main/java/org/objenesis/instantiator/perc/PercInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/perc/PercInstantiator.java
@@ -1,63 +1,67 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator.perc;

-

-import java.io.ObjectInputStream;

-import java.lang.reflect.Method;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Instantiates a class by making a call to internal Perc private methods. It is only supposed to

- * work on Perc JVMs. This instantiator will not call any constructors. The code was provided by

- * Aonix Perc support team.

- * 

- * @author Henri Tremblay

- * @see org.objenesis.instantiator.ObjectInstantiator

- */

-public class PercInstantiator implements ObjectInstantiator {

-

-	private final Method newInstanceMethod;

-

-	private final Object[] typeArgs = new Object[] { null, Boolean.FALSE };

-

-	public PercInstantiator(Class type) {

-

-		typeArgs[0] = type;

-

-		try {

-			newInstanceMethod = ObjectInputStream.class.getDeclaredMethod("newInstance",

-					new Class[] { Class.class, Boolean.TYPE });

-			newInstanceMethod.setAccessible(true);

-		}

-      catch(RuntimeException e) {

-			throw new ObjenesisException(e);

-		}

-      catch(NoSuchMethodException e) {

-         throw new ObjenesisException(e);

-      }

-	}

-

-	public Object newInstance() {

-		try {

-			return newInstanceMethod.invoke(null, typeArgs);

-		} catch (Exception e) {

-			throw new ObjenesisException(e);

-		}

-	}

-

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.perc;
+
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+/**
+ * Instantiates a class by making a call to internal Perc private methods. It is only supposed to
+ * work on Perc JVMs. This instantiator will not call any constructors. The code was provided by
+ * Aonix Perc support team.
+ *
+ * @author Henri Tremblay
+ * @see org.objenesis.instantiator.ObjectInstantiator
+ */
+@Instantiator(Typology.STANDARD)
+public class PercInstantiator<T> implements ObjectInstantiator<T> {
+
+	private final Method newInstanceMethod;
+
+	private final Object[] typeArgs = new Object[] { null, Boolean.FALSE };
+
+	public PercInstantiator(Class<T> type) {
+
+		typeArgs[0] = type;
+
+		try {
+         newInstanceMethod = ObjectInputStream.class.getDeclaredMethod("newInstance", Class.class,
+            Boolean.TYPE);
+			newInstanceMethod.setAccessible(true);
+		}
+      catch(RuntimeException e) {
+			throw new ObjenesisException(e);
+		}
+      catch(NoSuchMethodException e) {
+         throw new ObjenesisException(e);
+      }
+	}
+
+	@SuppressWarnings("unchecked")
+   public T newInstance() {
+		try {
+         return (T) newInstanceMethod.invoke(null, typeArgs);
+		} catch (Exception e) {
+			throw new ObjenesisException(e);
+		}
+	}
+
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/perc/PercSerializationInstantiator.java b/main/src/main/java/org/objenesis/instantiator/perc/PercSerializationInstantiator.java
index 8dd8016..b3a140e 100644
--- a/main/src/main/java/org/objenesis/instantiator/perc/PercSerializationInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/perc/PercSerializationInstantiator.java
@@ -1,96 +1,100 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator.perc;

-

-import java.io.ObjectInputStream;

-import java.io.Serializable;

-import java.lang.reflect.InvocationTargetException;

-import java.lang.reflect.Method;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Instantiates a class by making a call to internal Perc private methods. It is only supposed to

- * work on Perc JVMs. This instantiator will create classes in a way compatible with serialization,

- * calling the first non-serializable superclass' no-arg constructor. <p/> Based on code provided by

- * Aonix but <b>doesn't work right now</b>

- * 

- * @author Henri Tremblay

- * @see org.objenesis.instantiator.ObjectInstantiator

- */

-public class PercSerializationInstantiator implements ObjectInstantiator {

-

-   private Object[] typeArgs;

-

-   private final java.lang.reflect.Method newInstanceMethod;

-

-   public PercSerializationInstantiator(Class type) {

-

-      // Find the first unserializable parent class

-      Class unserializableType = type;

-

-      while(Serializable.class.isAssignableFrom(unserializableType)) {

-         unserializableType = unserializableType.getSuperclass();

-      }

-

-      try {

-         // Get the special Perc method to call

-         Class percMethodClass = Class.forName("COM.newmonics.PercClassLoader.Method");

-

-         newInstanceMethod = ObjectInputStream.class.getDeclaredMethod("noArgConstruct",

-            new Class[] {Class.class, Object.class, percMethodClass});

-         newInstanceMethod.setAccessible(true);

-

-         // Create invoke params

-         Class percClassClass = Class.forName("COM.newmonics.PercClassLoader.PercClass");

-         Method getPercClassMethod = percClassClass.getDeclaredMethod("getPercClass",

-            new Class[] {Class.class});

-         Object someObject = getPercClassMethod.invoke(null, new Object[] {unserializableType});

-         Method findMethodMethod = someObject.getClass().getDeclaredMethod("findMethod",

-            new Class[] {String.class});

-         Object percMethod = findMethodMethod.invoke(someObject, new Object[] {"<init>()V"});

-

-         typeArgs = new Object[] {unserializableType, type, percMethod};

-

-      }

-      catch(ClassNotFoundException e) {

-         throw new ObjenesisException(e);

-      }

-      catch(NoSuchMethodException e) {

-         throw new ObjenesisException(e);

-      }

-      catch(InvocationTargetException e) {

-         throw new ObjenesisException(e);

-      }

-      catch(IllegalAccessException e) {

-         throw new ObjenesisException(e);

-      }

-   }

-

-   public Object newInstance() {

-      try {

-         return newInstanceMethod.invoke(null, typeArgs);

-      }

-      catch(IllegalAccessException e) {

-         throw new ObjenesisException(e);

-      }

-      catch(InvocationTargetException e) {

-         throw new ObjenesisException(e);

-      }

-   }

-

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.perc;
+
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+/**
+ * Instantiates a class by making a call to internal Perc private methods. It is only supposed to
+ * work on Perc JVMs. This instantiator will create classes in a way compatible with serialization,
+ * calling the first non-serializable superclass' no-arg constructor.
+ * <p>
+ * Based on code provided by Aonix but <b>doesn't work right now</b>
+ *
+ * @author Henri Tremblay
+ * @see org.objenesis.instantiator.ObjectInstantiator
+ */
+@Instantiator(Typology.SERIALIZATION)
+public class PercSerializationInstantiator<T> implements ObjectInstantiator<T> {
+
+   private Object[] typeArgs;
+
+   private final Method newInstanceMethod;
+
+   public PercSerializationInstantiator(Class<T> type) {
+
+      // Find the first unserializable parent class
+      Class<? super T> unserializableType = type;
+
+      while(Serializable.class.isAssignableFrom(unserializableType)) {
+         unserializableType = unserializableType.getSuperclass();
+      }
+
+      try {
+         // Get the special Perc method to call
+         Class<?> percMethodClass = Class.forName("COM.newmonics.PercClassLoader.Method");
+
+         newInstanceMethod = ObjectInputStream.class.getDeclaredMethod("noArgConstruct",
+            new Class[] {Class.class, Object.class, percMethodClass});
+         newInstanceMethod.setAccessible(true);
+
+         // Create invoke params
+         Class<?> percClassClass = Class.forName("COM.newmonics.PercClassLoader.PercClass");
+         Method getPercClassMethod = percClassClass.getDeclaredMethod("getPercClass", Class.class);
+         Object someObject = getPercClassMethod.invoke(null, unserializableType);
+         Method findMethodMethod = someObject.getClass().getDeclaredMethod("findMethod",
+            new Class[] {String.class});
+         Object percMethod = findMethodMethod.invoke(someObject, "<init>()V");
+
+         typeArgs = new Object[] {unserializableType, type, percMethod};
+
+      }
+      catch(ClassNotFoundException e) {
+         throw new ObjenesisException(e);
+      }
+      catch(NoSuchMethodException e) {
+         throw new ObjenesisException(e);
+      }
+      catch(InvocationTargetException e) {
+         throw new ObjenesisException(e);
+      }
+      catch(IllegalAccessException e) {
+         throw new ObjenesisException(e);
+      }
+   }
+
+   @SuppressWarnings("unchecked")
+   public T newInstance() {
+      try {
+         return (T) newInstanceMethod.invoke(null, typeArgs);
+      }
+      catch(IllegalAccessException e) {
+         throw new ObjenesisException(e);
+      }
+      catch(InvocationTargetException e) {
+         throw new ObjenesisException(e);
+      }
+   }
+
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/sun/MagicInstantiator.java b/main/src/main/java/org/objenesis/instantiator/sun/MagicInstantiator.java
new file mode 100644
index 0000000..4ece96e
--- /dev/null
+++ b/main/src/main/java/org/objenesis/instantiator/sun/MagicInstantiator.java
@@ -0,0 +1,285 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.sun;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+import org.objenesis.instantiator.basic.ClassDefinitionUtils;
+
+import static org.objenesis.instantiator.basic.ClassDefinitionUtils.*;
+
+/**
+ * This instantiator will correctly bypass the constructors by instantiating the class using the default
+ * constructor from Object. It will be allowed to do so by extending {@code MagicAccessorImpl} which prevents
+ * its children to be verified by the class loader
+ *
+ * @author Henri Tremblay
+ */
+@Instantiator(Typology.STANDARD)
+public class MagicInstantiator<T> implements ObjectInstantiator<T> {
+
+   private static final int INDEX_CLASS_THIS = 1;
+   private static final int INDEX_CLASS_SUPERCLASS = 2;
+   private static final int INDEX_UTF8_CONSTRUCTOR_NAME = 3;
+   private static final int INDEX_UTF8_CONSTRUCTOR_DESC = 4;
+   private static final int INDEX_UTF8_CODE_ATTRIBUTE = 5;
+   private static final int INDEX_UTF8_INSTANTIATOR_CLASS = 7;
+   private static final int INDEX_UTF8_SUPERCLASS = 8;
+   private static final int INDEX_CLASS_INTERFACE = 9;
+   private static final int INDEX_UTF8_INTERFACE = 10;
+   private static final int INDEX_UTF8_NEWINSTANCE_NAME = 11;
+   private static final int INDEX_UTF8_NEWINSTANCE_DESC = 12;
+   private static final int INDEX_METHODREF_OBJECT_CONSTRUCTOR = 13;
+   private static final int INDEX_CLASS_OBJECT = 14;
+   private static final int INDEX_UTF8_OBJECT = 15;
+   private static final int INDEX_NAMEANDTYPE_DEFAULT_CONSTRUCTOR = 16;
+   private static final int INDEX_CLASS_TYPE = 17;
+   private static final int INDEX_UTF8_TYPE = 18;
+
+   private static int CONSTANT_POOL_COUNT = 19;
+
+   private static final byte[] CONSTRUCTOR_CODE = { OPS_aload_0, OPS_invokespecial, 0, INDEX_METHODREF_OBJECT_CONSTRUCTOR, OPS_return};
+   private static final int CONSTRUCTOR_CODE_ATTRIBUTE_LENGTH = 12 + CONSTRUCTOR_CODE.length;
+
+   private static final byte[] NEWINSTANCE_CODE = { OPS_new, 0, INDEX_CLASS_TYPE, OPS_dup, OPS_invokespecial, 0, INDEX_METHODREF_OBJECT_CONSTRUCTOR, OPS_areturn};
+   private static final int NEWINSTANCE_CODE_ATTRIBUTE_LENGTH = 12 + NEWINSTANCE_CODE.length;
+
+   private static final String CONSTRUCTOR_NAME = "<init>";
+   private static final String CONSTRUCTOR_DESC = "()V";
+
+   private ObjectInstantiator<T> instantiator;
+
+   public MagicInstantiator(Class<T> type) {
+      instantiator = newInstantiatorOf(type);
+   }
+
+   /**
+    * Get the underlying instantiator.
+    *
+    * {@link MagicInstantiator} is a wrapper around another object
+    * which implements {@link ObjectInstantiator} interface.
+    * This method exposes that instantiator.
+    *
+    * @return the underlying instantiator
+    */
+   public ObjectInstantiator<T> getInstantiator() {
+      return instantiator;
+   }
+
+   private <T> ObjectInstantiator<T> newInstantiatorOf(Class<T> type) {
+      String suffix = type.getSimpleName();
+      String className = getClass().getName() + "$$$" + suffix;
+
+      Class<ObjectInstantiator<T>> clazz = getExistingClass(getClass().getClassLoader(), className);
+
+      if(clazz == null) {
+         byte[] classBytes = writeExtendingClass(type, className);
+
+         try {
+            clazz = ClassDefinitionUtils.defineClass(className, classBytes, getClass().getClassLoader());
+         } catch (Exception e) {
+            throw new ObjenesisException(e);
+         }
+      }
+
+      try {
+         return clazz.newInstance();
+      } catch (InstantiationException e) {
+         throw new ObjenesisException(e);
+      } catch (IllegalAccessException e) {
+         throw new ObjenesisException(e);
+      }
+   }
+
+   /**
+    * Will generate the bytes for a class extending the type passed in parameter. This class will
+    * only have an empty default constructor
+    *
+    * @param type type to extend
+    * @param className name of the wrapped instantiator class
+    * @return the byte for the class
+    * @throws ObjenesisException is something goes wrong
+    */
+   private byte[] writeExtendingClass(Class<?> type, String className) {
+      String clazz = classNameToInternalClassName(className);
+
+      DataOutputStream in = null;
+      ByteArrayOutputStream bIn = new ByteArrayOutputStream(1000); // 1000 should be large enough to fit the entire class
+      try {
+         in = new DataOutputStream(bIn);
+
+         in.write(MAGIC);
+         in.write(VERSION);
+         in.writeShort(CONSTANT_POOL_COUNT);
+
+         // set all the constant pool here
+
+         // 1. class
+         in.writeByte(CONSTANT_Class);
+         in.writeShort(INDEX_UTF8_INSTANTIATOR_CLASS);
+
+         // 2. super class
+         in.writeByte(CONSTANT_Class);
+         in.writeShort(INDEX_UTF8_SUPERCLASS);
+
+         // 3. default constructor name
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF(CONSTRUCTOR_NAME);
+
+         // 4. default constructor description
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF(CONSTRUCTOR_DESC);
+
+         // 5. Code
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF("Code");
+
+         // 6. Class name
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF("L" + clazz + ";");
+
+         // 7. Class name (again)
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF(clazz);
+
+         // 8. Superclass name
+         in.writeByte(CONSTANT_Utf8);
+//         in.writeUTF("java/lang/Object");
+         in.writeUTF("sun/reflect/MagicAccessorImpl");
+
+         // 9. ObjectInstantiator interface
+         in.writeByte(CONSTANT_Class);
+         in.writeShort(INDEX_UTF8_INTERFACE);
+
+         // 10. ObjectInstantiator name
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF(ObjectInstantiator.class.getName().replace('.', '/'));
+
+         // 11. newInstance name
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF("newInstance");
+
+         // 12. newInstance desc
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF("()Ljava/lang/Object;");
+
+         // 13. Methodref to the Object constructor
+         in.writeByte(CONSTANT_Methodref);
+         in.writeShort(INDEX_CLASS_OBJECT);
+         in.writeShort(INDEX_NAMEANDTYPE_DEFAULT_CONSTRUCTOR);
+
+         // 14. Object class
+         in.writeByte(CONSTANT_Class);
+         in.writeShort(INDEX_UTF8_OBJECT);
+
+         // 15. Object class name
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF("java/lang/Object");
+
+         // 16. Default constructor name and type
+         in.writeByte(CONSTANT_NameAndType);
+         in.writeShort(INDEX_UTF8_CONSTRUCTOR_NAME);
+         in.writeShort(INDEX_UTF8_CONSTRUCTOR_DESC);
+
+         // 17. Type to instantiate class
+         in.writeByte(CONSTANT_Class);
+         in.writeShort(INDEX_UTF8_TYPE);
+
+         // 18. Type to instantiate name
+         in.writeByte(CONSTANT_Utf8);
+         in.writeUTF(classNameToInternalClassName(type.getName()));
+
+         // end of constant pool
+
+         // access flags: We want public, ACC_SUPER is always there
+         in.writeShort(ACC_PUBLIC | ACC_SUPER | ACC_FINAL);
+
+         // this class index in the constant pool
+         in.writeShort(INDEX_CLASS_THIS);
+
+         // super class index in the constant pool
+         in.writeShort(INDEX_CLASS_SUPERCLASS);
+
+         // interfaces implemented count (we have none)
+         in.writeShort(1);
+         in.writeShort(INDEX_CLASS_INTERFACE);
+
+         // fields count (we have none)
+         in.writeShort(0);
+
+         // method count (we have two: the default constructor and newInstance)
+         in.writeShort(2);
+
+         // default constructor method_info
+         in.writeShort(ACC_PUBLIC);
+         in.writeShort(INDEX_UTF8_CONSTRUCTOR_NAME); // index of the method name (<init>)
+         in.writeShort(INDEX_UTF8_CONSTRUCTOR_DESC); // index of the description
+         in.writeShort(1); // number of attributes: only one, the code
+
+         // code attribute of the default constructor
+         in.writeShort(INDEX_UTF8_CODE_ATTRIBUTE);
+         in.writeInt(CONSTRUCTOR_CODE_ATTRIBUTE_LENGTH); // attribute length
+         in.writeShort(0); // max_stack
+         in.writeShort(1); // max_locals
+         in.writeInt(CONSTRUCTOR_CODE.length); // code length
+         in.write(CONSTRUCTOR_CODE);
+         in.writeShort(0); // exception_table_length = 0
+         in.writeShort(0); // attributes count = 0, no need to have LineNumberTable and LocalVariableTable
+
+         // newInstance method_info
+         in.writeShort(ACC_PUBLIC);
+         in.writeShort(INDEX_UTF8_NEWINSTANCE_NAME); // index of the method name (newInstance)
+         in.writeShort(INDEX_UTF8_NEWINSTANCE_DESC); // index of the description
+         in.writeShort(1); // number of attributes: only one, the code
+
+         // code attribute of newInstance
+         in.writeShort(INDEX_UTF8_CODE_ATTRIBUTE);
+         in.writeInt(NEWINSTANCE_CODE_ATTRIBUTE_LENGTH); // attribute length
+         in.writeShort(2); // max_stack
+         in.writeShort(1); // max_locals
+         in.writeInt(NEWINSTANCE_CODE.length); // code length
+         in.write(NEWINSTANCE_CODE);
+         in.writeShort(0); // exception_table_length = 0
+         in.writeShort(0); // attributes count = 0, no need to have LineNumberTable and LocalVariableTable
+
+         // class attributes
+         in.writeShort(0); // none. No need to have a source file attribute
+
+      } catch (IOException e) {
+         throw new ObjenesisException(e);
+      } finally {
+         if(in != null) {
+            try {
+               in.close();
+            } catch (IOException e) {
+               throw new ObjenesisException(e);
+            }
+         }
+      }
+
+      return bIn.toByteArray();
+   }
+
+   public T newInstance() {
+      return instantiator.newInstance();
+   }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/sun/Sun13Instantiator.java b/main/src/main/java/org/objenesis/instantiator/sun/Sun13Instantiator.java
deleted file mode 100644
index 28c353a..0000000
--- a/main/src/main/java/org/objenesis/instantiator/sun/Sun13Instantiator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator.sun;

-

-import java.lang.reflect.InvocationTargetException;

-

-import org.objenesis.ObjenesisException;

-

-/**

- * Instantiates a class by making a call to internal Sun private methods. It is only supposed to

- * work on Sun HotSpot 1.3 JVM. This instantiator will not call any constructors.

- * 

- * @author Leonardo Mesquita

- * @see org.objenesis.instantiator.ObjectInstantiator

- */

-public class Sun13Instantiator extends Sun13InstantiatorBase {

-   public Sun13Instantiator(Class type) {

-      super(type);

-   }

-

-   public Object newInstance() {

-      try {

-         return allocateNewObjectMethod.invoke(null, new Object[] {type, Object.class});

-      }

-      catch(RuntimeException e) {

-         throw new ObjenesisException(e);

-      }

-      catch(IllegalAccessException e) {

-         throw new ObjenesisException(e);

-      }

-      catch(InvocationTargetException e) {

-         throw new ObjenesisException(e);

-      }

-   }

-

-}

diff --git a/main/src/main/java/org/objenesis/instantiator/sun/Sun13InstantiatorBase.java b/main/src/main/java/org/objenesis/instantiator/sun/Sun13InstantiatorBase.java
deleted file mode 100644
index 13073a1..0000000
--- a/main/src/main/java/org/objenesis/instantiator/sun/Sun13InstantiatorBase.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator.sun;

-

-import java.io.ObjectInputStream;

-import java.lang.reflect.Method;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Base class for Sun 1.3 based instantiators. It initializes reflection access to static method

- * ObjectInputStream.allocateNewObject.

- * 

- * @author Leonardo Mesquita

- */

-public abstract class Sun13InstantiatorBase implements ObjectInstantiator {

-   static Method allocateNewObjectMethod = null;

-

-   private static void initialize() {

-      if(allocateNewObjectMethod == null) {

-         try {

-            allocateNewObjectMethod = ObjectInputStream.class.getDeclaredMethod(

-               "allocateNewObject", new Class[] {Class.class, Class.class});

-            allocateNewObjectMethod.setAccessible(true);

-         }

-         catch(RuntimeException e) {

-            throw new ObjenesisException(e);

-         }

-         catch(NoSuchMethodException e) {

-            throw new ObjenesisException(e);

-         }

-      }

-   }

-

-   protected final Class type;

-

-   public Sun13InstantiatorBase(Class type) {

-      this.type = type;

-      initialize();

-   }

-

-   public abstract Object newInstance();

-

-}

diff --git a/main/src/main/java/org/objenesis/instantiator/sun/Sun13SerializationInstantiator.java b/main/src/main/java/org/objenesis/instantiator/sun/Sun13SerializationInstantiator.java
deleted file mode 100644
index 9669e57..0000000
--- a/main/src/main/java/org/objenesis/instantiator/sun/Sun13SerializationInstantiator.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator.sun;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.SerializationInstantiatorHelper;

-

-/**

- * Instantiates a class by making a call to internal Sun private methods. It is only supposed to

- * work on Sun HotSpot 1.3 JVM. This instantiator will create classes in a way compatible with

- * serialization, calling the first non-serializable superclass' no-arg constructor.

- * 

- * @author Leonardo Mesquita

- * @see org.objenesis.instantiator.ObjectInstantiator

- */

-public class Sun13SerializationInstantiator extends Sun13InstantiatorBase {

-   private final Class superType;

-

-   public Sun13SerializationInstantiator(Class type) {

-      super(type);

-      this.superType = SerializationInstantiatorHelper.getNonSerializableSuperClass(type);

-   }

-

-   public Object newInstance() {

-      try {

-         return allocateNewObjectMethod.invoke(null, new Object[] {type, superType});

-      }

-      catch(Exception e) {

-         throw new ObjenesisException(e);

-      }

-   }

-

-}

diff --git a/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactoryHelper.java b/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactoryHelper.java
index 5717b72..4396385 100644
--- a/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactoryHelper.java
+++ b/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactoryHelper.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.objenesis.instantiator.sun;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
@@ -29,18 +28,21 @@
  * 
  * @author Henri Tremblay
  */
+@SuppressWarnings("restriction")
 class SunReflectionFactoryHelper {
 
-   public static Constructor newConstructorForSerialization(Class type, Constructor constructor) {
-      Class reflectionFactoryClass = getReflectionFactoryClass();
+   @SuppressWarnings("unchecked")
+   public static <T> Constructor<T> newConstructorForSerialization(Class<T> type,
+      Constructor<?> constructor) {
+      Class<?> reflectionFactoryClass = getReflectionFactoryClass();
       Object reflectionFactory = createReflectionFactory(reflectionFactoryClass);
 
       Method newConstructorForSerializationMethod = getNewConstructorForSerializationMethod(
          reflectionFactoryClass);
 
       try {
-         return (Constructor) newConstructorForSerializationMethod.invoke(
-            reflectionFactory, new Object[] {type, constructor});
+         return (Constructor<T>) newConstructorForSerializationMethod.invoke(
+            reflectionFactory, type, constructor);
       }
       catch(IllegalArgumentException e) {
          throw new ObjenesisException(e);
@@ -53,7 +55,7 @@
       }
    }
 
-   private static Class getReflectionFactoryClass() {
+   private static Class<?> getReflectionFactoryClass() {
       try {
          return Class.forName("sun.reflect.ReflectionFactory");
       }
@@ -62,11 +64,11 @@
       }
    }
 
-   private static Object createReflectionFactory(Class reflectionFactoryClass) {
+   private static Object createReflectionFactory(Class<?> reflectionFactoryClass) {
       try {
          Method method = reflectionFactoryClass.getDeclaredMethod(
-            "getReflectionFactory", new Class[] {});
-         return method.invoke(null, new Object[] {});
+            "getReflectionFactory");
+         return method.invoke(null);
       }
       catch(NoSuchMethodException e) {
          throw new ObjenesisException(e);
@@ -82,10 +84,10 @@
       }
    }
 
-   private static Method getNewConstructorForSerializationMethod(Class reflectionFactoryClass) {
+   private static Method getNewConstructorForSerializationMethod(Class<?> reflectionFactoryClass) {
       try {
          return reflectionFactoryClass.getDeclaredMethod(
-            "newConstructorForSerialization", new Class[] {Class.class, Constructor.class});
+            "newConstructorForSerialization", Class.class, Constructor.class);
       }
       catch(NoSuchMethodException e) {
          throw new ObjenesisException(e);
diff --git a/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactoryInstantiator.java b/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactoryInstantiator.java
index fa30448..f1ae3a7 100644
--- a/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactoryInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactoryInstantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,28 +19,31 @@
 
 import org.objenesis.ObjenesisException;
 import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
 
 /**
  * Instantiates an object, WITHOUT calling it's constructor, using internal
  * sun.reflect.ReflectionFactory - a class only available on JDK's that use Sun's 1.4 (or later)
  * Java implementation. This is the best way to instantiate an object without any side effects
  * caused by the constructor - however it is not available on every platform.
- * 
+ *
  * @author Joe Walnes
  * @see ObjectInstantiator
  */
-public class SunReflectionFactoryInstantiator implements ObjectInstantiator {
+@Instantiator(Typology.STANDARD)
+public class SunReflectionFactoryInstantiator<T> implements ObjectInstantiator<T> {
 
-   private final Constructor mungedConstructor;
+   private final Constructor<T> mungedConstructor;
 
-   public SunReflectionFactoryInstantiator(Class type) {
-      Constructor javaLangObjectConstructor = getJavaLangObjectConstructor();
+   public SunReflectionFactoryInstantiator(Class<T> type) {
+      Constructor<Object> javaLangObjectConstructor = getJavaLangObjectConstructor();
       mungedConstructor = SunReflectionFactoryHelper.newConstructorForSerialization(
           type, javaLangObjectConstructor);
       mungedConstructor.setAccessible(true);
    }
 
-   public Object newInstance() {
+   public T newInstance() {
       try {
          return mungedConstructor.newInstance((Object[]) null);
       }
@@ -49,7 +52,7 @@
       }
    }
 
-   private static Constructor getJavaLangObjectConstructor() {
+   private static Constructor<Object> getJavaLangObjectConstructor() {
       try {
          return Object.class.getConstructor((Class[]) null);
       }
diff --git a/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactorySerializationInstantiator.java b/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactorySerializationInstantiator.java
index e6bb2c8..21e024a 100644
--- a/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactorySerializationInstantiator.java
+++ b/main/src/main/java/org/objenesis/instantiator/sun/SunReflectionFactorySerializationInstantiator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
 import org.objenesis.ObjenesisException;
 import org.objenesis.instantiator.ObjectInstantiator;
 import org.objenesis.instantiator.SerializationInstantiatorHelper;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
 
 /**
  * Instantiates an object using internal sun.reflect.ReflectionFactory - a class only available on
@@ -28,24 +30,26 @@
  * a way compatible with serialization, calling the first non-serializable superclass' no-arg
  * constructor. This is the best way to instantiate an object without any side effects caused by the
  * constructor - however it is not available on every platform.
- * 
+ *
  * @author Leonardo Mesquita
  * @see ObjectInstantiator
  */
-public class SunReflectionFactorySerializationInstantiator implements ObjectInstantiator {
+@Instantiator(Typology.SERIALIZATION)
+public class SunReflectionFactorySerializationInstantiator<T> implements ObjectInstantiator<T> {
 
-   private final Constructor mungedConstructor;
+   private final Constructor<T> mungedConstructor;
 
-   public SunReflectionFactorySerializationInstantiator(Class type) {
-	  Class nonSerializableAncestor = SerializationInstantiatorHelper.getNonSerializableSuperClass(type);
-      
-      Constructor nonSerializableAncestorConstructor;
+   public SunReflectionFactorySerializationInstantiator(Class<T> type) {
+      Class<? super T> nonSerializableAncestor = SerializationInstantiatorHelper
+         .getNonSerializableSuperClass(type);
+
+      Constructor<? super T> nonSerializableAncestorConstructor;
       try {
          nonSerializableAncestorConstructor = nonSerializableAncestor
             .getConstructor((Class[]) null);
       }
       catch(NoSuchMethodException e) {
-         throw new ObjenesisException(new NotSerializableException(type+" has no suitable superclass constructor"));         
+         throw new ObjenesisException(new NotSerializableException(type+" has no suitable superclass constructor"));
       }
 
       mungedConstructor = SunReflectionFactoryHelper.newConstructorForSerialization(
@@ -53,7 +57,7 @@
       mungedConstructor.setAccessible(true);
    }
 
-   public Object newInstance() {
+   public T newInstance() {
       try {
          return mungedConstructor.newInstance((Object[]) null);
       }
diff --git a/main/src/main/java/org/objenesis/instantiator/sun/UnsafeFactoryInstantiator.java b/main/src/main/java/org/objenesis/instantiator/sun/UnsafeFactoryInstantiator.java
new file mode 100644
index 0000000..6ccb070
--- /dev/null
+++ b/main/src/main/java/org/objenesis/instantiator/sun/UnsafeFactoryInstantiator.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.sun;
+
+import sun.misc.Unsafe;
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+import java.lang.reflect.Field;
+
+/**
+ * Instantiates an object, WITHOUT calling it's constructor, using
+ * sun.misc.Unsafe.allocateInstance(). Unsafe and its methods are implemented by most
+ * modern JVMs.
+ *
+ * @author Henri Tremblay
+ * @see ObjectInstantiator
+ */
+@SuppressWarnings("restriction")
+@Instantiator(Typology.STANDARD)
+public class UnsafeFactoryInstantiator<T> implements ObjectInstantiator<T> {
+
+   private static Unsafe unsafe;
+   private final Class<T> type;
+
+   public UnsafeFactoryInstantiator(Class<T> type) {
+      if (unsafe == null) {
+         Field f;
+         try {
+            f = Unsafe.class.getDeclaredField("theUnsafe");
+         } catch (NoSuchFieldException e) {
+            throw new ObjenesisException(e);
+         }
+         f.setAccessible(true);
+         try {
+            unsafe = (Unsafe) f.get(null);
+         } catch (IllegalAccessException e) {
+            throw new ObjenesisException(e);
+         }
+      }
+      this.type = type;
+   }
+
+   public T newInstance() {
+      try {
+         return type.cast(unsafe.allocateInstance(type));
+      } catch (InstantiationException e) {
+         throw new ObjenesisException(e);
+      }
+   }
+}
diff --git a/main/src/main/java/org/objenesis/strategy/BaseInstantiatorStrategy.java b/main/src/main/java/org/objenesis/strategy/BaseInstantiatorStrategy.java
index 6161576..909420a 100644
--- a/main/src/main/java/org/objenesis/strategy/BaseInstantiatorStrategy.java
+++ b/main/src/main/java/org/objenesis/strategy/BaseInstantiatorStrategy.java
@@ -1,54 +1,25 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.strategy;

-

-/**

- * Base {@link InstantiatorStrategy} class basically containing helpful constant to sort out JVMs.

- * 

- * @author Henri Tremblay

- */

-public abstract class BaseInstantiatorStrategy implements InstantiatorStrategy {

-

-   /** JVM_NAME prefix for JRockit */

-   protected static final String JROCKIT = "BEA";

-

-   /** JVM_NAME prefix for GCJ */

-   protected static final String GNU = "GNU libgcj";

-

-   /** JVM_NAME prefix for Sun Java HotSpot */

-   protected static final String SUN = "Java HotSpot";

-

-   /** JVM_NAME prefix for Aonix PERC */

-   protected static final String PERC = "PERC";

-   

-   /** JVM_NAME prefix for Dalvik/Android */

-   protected static final String DALVIK = "Dalvik";

-   

-   /** JVM version */

-   protected static final String VM_VERSION = System.getProperty("java.runtime.version");

-

-   /** JVM version */

-   protected static final String VM_INFO = System.getProperty("java.vm.info");

-

-   /** Vendor version */

-   protected static final String VENDOR_VERSION = System.getProperty("java.vm.version");

-

-   /** Vendor name */

-   protected static final String VENDOR = System.getProperty("java.vm.vendor");

-

-   /** JVM name */

-   protected static final String JVM_NAME = System.getProperty("java.vm.name");

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.strategy;
+
+/**
+ * Base {@link InstantiatorStrategy} class basically. Only implements {@link InstantiatorStrategy}
+ * 
+ * @author Henri Tremblay
+ */
+public abstract class BaseInstantiatorStrategy implements InstantiatorStrategy {
+
+}
diff --git a/main/src/main/java/org/objenesis/strategy/InstantiatorStrategy.java b/main/src/main/java/org/objenesis/strategy/InstantiatorStrategy.java
index dfaa84e..657cb2a 100644
--- a/main/src/main/java/org/objenesis/strategy/InstantiatorStrategy.java
+++ b/main/src/main/java/org/objenesis/strategy/InstantiatorStrategy.java
@@ -1,34 +1,35 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.strategy;

-

-import org.objenesis.instantiator.ObjectInstantiator;

-

-/**

- * Defines a strategy to determine the best instantiator for a class.

- * 

- * @author Henri Tremblay

- */

-public interface InstantiatorStrategy {

-

-   /**

-    * Create a dedicated instantiator for the given class

-    * 

-    * @param type Class that will be instantiate

-    * @return Dedicated instantiator

-    */

-   ObjectInstantiator newInstantiatorOf(Class type);

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.strategy;
+
+import org.objenesis.instantiator.ObjectInstantiator;
+
+/**
+ * Defines a strategy to determine the best instantiator for a class.
+ * 
+ * @author Henri Tremblay
+ */
+public interface InstantiatorStrategy {
+
+   /**
+    * Create a dedicated instantiator for the given class
+    *
+    * @param <T> Type to instantiate
+    * @param type Class that will be instantiated
+    * @return Dedicated instantiator
+    */
+   <T> ObjectInstantiator<T> newInstantiatorOf(Class<T> type);
+}
diff --git a/main/src/main/java/org/objenesis/strategy/PlatformDescription.java b/main/src/main/java/org/objenesis/strategy/PlatformDescription.java
new file mode 100644
index 0000000..8024567
--- /dev/null
+++ b/main/src/main/java/org/objenesis/strategy/PlatformDescription.java
@@ -0,0 +1,198 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.strategy;
+
+import org.objenesis.ObjenesisException;
+
+import java.lang.reflect.Field;
+
+/**
+ * List of constants describing the currently used platform.
+ *
+ * @author Henri Tremblay
+ */
+public final class PlatformDescription {
+
+   /** JVM_NAME prefix for JRockit */
+   public static final String JROCKIT = "BEA";
+
+   /** JVM_NAME prefix for GCJ */
+   public static final String GNU = "GNU libgcj";
+
+   /** JVM_NAME prefix for Java HotSpot */
+   public static final String HOTSPOT = "Java HotSpot";
+
+   /**
+    * JVM_NAME prefix for Java HotSpot
+    *
+    * @deprecated Use {@link #HOTSPOT} instead
+    */
+   @Deprecated
+   public static final String SUN = HOTSPOT;
+
+   /** JVM_NAME prefix for the OpenJDK */
+   public static final String OPENJDK = "OpenJDK";
+
+   /** JVM_NAME prefix for Aonix PERC */
+   public static final String PERC = "PERC";
+
+   /** JVM_NAME prefix for Dalvik/Android */
+   public static final String DALVIK = "Dalvik";
+
+   /** Java specification version */
+   public static final String SPECIFICATION_VERSION = System
+      .getProperty("java.specification.version");
+
+   /** JVM version */
+   public static final String VM_VERSION = System.getProperty("java.runtime.version");
+
+   /** JVM version */
+   public static final String VM_INFO = System.getProperty("java.vm.info");
+
+   /** VM vendor version */
+   public static final String VENDOR_VERSION = System.getProperty("java.vm.version");
+
+   /** VM vendor name */
+   public static final String VENDOR = System.getProperty("java.vm.vendor");
+
+   /** JVM name */
+   public static final String JVM_NAME = System.getProperty("java.vm.name");
+
+   /** Android version. Will be 0 for none android platform */
+   public static final int ANDROID_VERSION = getAndroidVersion();
+
+   /** Flag telling if this version of Android is based on the OpenJDK */
+   public static final boolean IS_ANDROID_OPENJDK = getIsAndroidOpenJDK();
+
+   /** Google App Engine version or null is we are not on GAE */
+   public static final String GAE_VERSION = getGaeRuntimeVersion();
+
+   /**
+    * Describes the platform. Outputs Java version and vendor.
+    *
+    * @return Description of the current platform
+    */
+   public static String describePlatform() {
+      String desc = "Java " + SPECIFICATION_VERSION + " ("
+              + "VM vendor name=\"" + VENDOR + "\", "
+              + "VM vendor version=" + VENDOR_VERSION + ", "
+              + "JVM name=\"" + JVM_NAME + "\", "
+              + "JVM version=" + VM_VERSION + ", "
+              + "JVM info=" + VM_INFO;
+
+      // Add the API level is it's an Android platform
+      int androidVersion = ANDROID_VERSION;
+      if(androidVersion != 0) {
+         desc += ", API level=" + ANDROID_VERSION;
+      }
+      desc += ")";
+
+      return desc;
+   }
+
+   /**
+    * Check if the current JVM is of the type passed in parameter. Normally, this will be a constant
+    * from this class. We basically do
+    * <code>System.getProperty("java.vm.name").startWith(name)</code>.
+    *
+    * @param name jvm name we are looking for
+    * @return if it's the requested JVM
+    */
+   public static boolean isThisJVM(String name) {
+      return JVM_NAME.startsWith(name);
+   }
+
+   /**
+    * Check if this JVM is an Android JVM based on OpenJDK.
+    *
+    * @return if it's an Android version based on the OpenJDK. Will return false if this JVM isn't an Android JVM at all
+     */
+   public static boolean isAndroidOpenJDK() {
+      return IS_ANDROID_OPENJDK;
+   }
+
+   private static boolean getIsAndroidOpenJDK() {
+      if(getAndroidVersion() == 0) {
+         return false; // Not android at all
+      }
+      // Sadly, Android N is still API 23. So we can't base ourselves on the API level to know if it is an OpenJDK
+      // version or not
+      String bootClasspath = System.getProperty("java.boot.class.path");
+      return bootClasspath != null && bootClasspath.toLowerCase().contains("core-oj.jar");
+   }
+
+   public static boolean isGoogleAppEngine() {
+      return GAE_VERSION != null;
+   }
+
+   private static String getGaeRuntimeVersion() {
+      return System.getProperty("com.google.appengine.runtime.version");
+   }
+
+   private static int getAndroidVersion() {
+      if(!isThisJVM(DALVIK)) {
+         return 0;
+      }
+      return getAndroidVersion0();
+   }
+
+   private static int getAndroidVersion0() {
+      Class<?> clazz;
+      try {
+         clazz = Class.forName("android.os.Build$VERSION");
+      }
+      catch(ClassNotFoundException e) {
+         throw new ObjenesisException(e);
+      }
+      Field field;
+      try {
+         field = clazz.getField("SDK_INT");
+      }
+      catch(NoSuchFieldException e) {
+         // Might be a really old API (before 4), go for SDK
+         return getOldAndroidVersion(clazz);
+      }
+      int version;
+      try {
+         version = (Integer) field.get(null);
+      }
+      catch(IllegalAccessException e) {
+         throw new RuntimeException(e);
+      }
+      return version;
+   }
+
+   private static int getOldAndroidVersion(Class<?> versionClass) {
+      Field field;
+      try {
+         field = versionClass.getField("SDK");
+      }
+      catch(NoSuchFieldException e) {
+         throw new ObjenesisException(e);
+      }
+      String version;
+      try {
+         version = (String) field.get(null);
+      }
+      catch(IllegalAccessException e) {
+         throw new RuntimeException(e);
+      }
+      return Integer.parseInt(version);
+   }
+
+   private PlatformDescription() {
+   }
+}
diff --git a/main/src/main/java/org/objenesis/strategy/SerializingInstantiatorStrategy.java b/main/src/main/java/org/objenesis/strategy/SerializingInstantiatorStrategy.java
index 1af2d3e..594598e 100644
--- a/main/src/main/java/org/objenesis/strategy/SerializingInstantiatorStrategy.java
+++ b/main/src/main/java/org/objenesis/strategy/SerializingInstantiatorStrategy.java
@@ -1,75 +1,86 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.strategy;

-

-import java.io.NotSerializableException;

-import java.io.Serializable;

-

-import org.objenesis.ObjenesisException;

-import org.objenesis.instantiator.ObjectInstantiator;

-import org.objenesis.instantiator.android.AndroidSerializationInstantiator;

-import org.objenesis.instantiator.basic.ObjectStreamClassInstantiator;

-import org.objenesis.instantiator.gcj.GCJSerializationInstantiator;

-import org.objenesis.instantiator.perc.PercSerializationInstantiator;

-import org.objenesis.instantiator.sun.Sun13SerializationInstantiator;

-

-/**

- * Guess the best serializing instantiator for a given class. The returned instantiator will

- * instantiate classes like the genuine java serialization framework (the constructor of the first

- * not serializable class will be called). Currently, the selection doesn't depend on the class. It

- * relies on the

- * <ul>

- * <li>JVM version</li>

- * <li>JVM vendor</li>

- * <li>JVM vendor version</li>

- * </ul>

- * However, instantiators are stateful and so dedicated to their class.

- * 

- * @author Henri Tremblay

- * @see ObjectInstantiator

- */

-public class SerializingInstantiatorStrategy extends BaseInstantiatorStrategy {

-

-   /**

-    * Return an {@link ObjectInstantiator} allowing to create instance following the java

-    * serialization framework specifications.

-    * 

-    * @param type Class to instantiate

-    * @return The ObjectInstantiator for the class

-    */

-   public ObjectInstantiator newInstantiatorOf(Class type) {

-      if(!Serializable.class.isAssignableFrom(type)) {

-         throw new ObjenesisException(new NotSerializableException(type+" not serializable"));

-      }

-      if(JVM_NAME.startsWith(SUN)) {

-         if(VM_VERSION.startsWith("1.3")) {

-            return new Sun13SerializationInstantiator(type);

-         }

-      }

-      else if(JVM_NAME.startsWith(DALVIK)) {

-         return new AndroidSerializationInstantiator(type);

-      }

-      else if(JVM_NAME.startsWith(GNU)) {

-         return new GCJSerializationInstantiator(type);

-      }

-      else if(JVM_NAME.startsWith(PERC)) {

-    	  return new PercSerializationInstantiator(type);

-      }

-      

-      return new ObjectStreamClassInstantiator(type);

-   }

-

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.strategy;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.instantiator.android.AndroidSerializationInstantiator;
+import org.objenesis.instantiator.basic.ObjectInputStreamInstantiator;
+import org.objenesis.instantiator.basic.ObjectStreamClassInstantiator;
+import org.objenesis.instantiator.gcj.GCJSerializationInstantiator;
+import org.objenesis.instantiator.perc.PercSerializationInstantiator;
+import org.objenesis.instantiator.sun.SunReflectionFactorySerializationInstantiator;
+
+import java.io.NotSerializableException;
+import java.io.Serializable;
+
+import static org.objenesis.strategy.PlatformDescription.*;
+
+/**
+ * Guess the best serializing instantiator for a given class. The returned instantiator will
+ * instantiate classes like the genuine java serialization framework (the constructor of the first
+ * not serializable class will be called). Currently, the selection doesn't depend on the class. It
+ * relies on the
+ * <ul>
+ * <li>JVM version</li>
+ * <li>JVM vendor</li>
+ * <li>JVM vendor version</li>
+ * </ul>
+ * However, instantiators are stateful and so dedicated to their class.
+ *
+ * @author Henri Tremblay
+ * @see ObjectInstantiator
+ */
+public class SerializingInstantiatorStrategy extends BaseInstantiatorStrategy {
+
+   /**
+    * Return an {@link ObjectInstantiator} allowing to create instance following the java
+    * serialization framework specifications.
+    *
+    * @param type Class to instantiate
+    * @return The ObjectInstantiator for the class
+    */
+   public <T> ObjectInstantiator<T> newInstantiatorOf(Class<T> type) {
+      if(!Serializable.class.isAssignableFrom(type)) {
+         throw new ObjenesisException(new NotSerializableException(type+" not serializable"));
+      }
+      if(JVM_NAME.startsWith(HOTSPOT) || PlatformDescription.isThisJVM(OPENJDK)) {
+         if(isGoogleAppEngine()) {
+            return new ObjectInputStreamInstantiator<T>(type);
+         }
+         // ObjectStreamClassInstantiator uses setAccessible which isn't supported on JDK9
+         if(PlatformDescription.SPECIFICATION_VERSION.equals("9")) {
+            return new SunReflectionFactorySerializationInstantiator<T>(type);
+         }
+         return new ObjectStreamClassInstantiator<T>(type);
+      }
+      else if(JVM_NAME.startsWith(DALVIK)) {
+         if(PlatformDescription.isAndroidOpenJDK()) {
+            return new ObjectStreamClassInstantiator<T>(type);
+         }
+         return new AndroidSerializationInstantiator<T>(type);
+      }
+      else if(JVM_NAME.startsWith(GNU)) {
+         return new GCJSerializationInstantiator<T>(type);
+      }
+      else if(JVM_NAME.startsWith(PERC)) {
+         return new PercSerializationInstantiator<T>(type);
+      }
+
+      return new ObjectStreamClassInstantiator<T>(type);
+   }
+
+}
diff --git a/main/src/main/java/org/objenesis/strategy/SingleInstantiatorStrategy.java b/main/src/main/java/org/objenesis/strategy/SingleInstantiatorStrategy.java
new file mode 100644
index 0000000..b0e5b80
--- /dev/null
+++ b/main/src/main/java/org/objenesis/strategy/SingleInstantiatorStrategy.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.strategy;
+
+import org.objenesis.ObjenesisException;
+import org.objenesis.instantiator.ObjectInstantiator;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Strategy returning only one instantiator type. Useful if you know on which JVM Objenesis
+ * will be used and want to specify it explicitly.
+ *
+ * @author Henri Tremblay
+ */
+public class SingleInstantiatorStrategy implements InstantiatorStrategy {
+
+   private Constructor<?> constructor;
+
+   /**
+    * Create a strategy that will return always the same instantiator type. We assume this instantiator
+    * has one constructor taking the class to instantiate in parameter.
+    *
+    * @param <T> the type we want to instantiate
+    * @param instantiator the instantiator type
+    */
+   public <T extends ObjectInstantiator<?>> SingleInstantiatorStrategy(Class<T> instantiator) {
+      try {
+         constructor = instantiator.getConstructor(Class.class);
+      }
+      catch(NoSuchMethodException e) {
+         throw new ObjenesisException(e);
+      }
+   }
+
+   /**
+    * Return an instantiator for the wanted type and of the one and only type of instantiator returned by this
+    * class.
+    *
+    * @param <T> the type we want to instantiate
+    * @param type Class to instantiate
+    * @return The ObjectInstantiator for the class
+    */
+   @SuppressWarnings("unchecked")
+   public <T> ObjectInstantiator<T> newInstantiatorOf(Class<T> type) {
+      try {
+         return (ObjectInstantiator<T>) constructor.newInstance(type);
+      } catch (InstantiationException e) {
+         throw new ObjenesisException(e);
+      } catch (IllegalAccessException e) {
+         throw new ObjenesisException(e);
+      } catch (InvocationTargetException e) {
+         throw new ObjenesisException(e);
+      }
+   }
+}
diff --git a/main/src/main/java/org/objenesis/strategy/StdInstantiatorStrategy.java b/main/src/main/java/org/objenesis/strategy/StdInstantiatorStrategy.java
index 2b71d9a..4475d53 100644
--- a/main/src/main/java/org/objenesis/strategy/StdInstantiatorStrategy.java
+++ b/main/src/main/java/org/objenesis/strategy/StdInstantiatorStrategy.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,13 +16,19 @@
 package org.objenesis.strategy;
 
 import org.objenesis.instantiator.ObjectInstantiator;
-import org.objenesis.instantiator.android.AndroidInstantiator;
+import org.objenesis.instantiator.android.Android10Instantiator;
+import org.objenesis.instantiator.android.Android17Instantiator;
+import org.objenesis.instantiator.android.Android18Instantiator;
+import org.objenesis.instantiator.basic.AccessibleInstantiator;
+import org.objenesis.instantiator.basic.ObjectInputStreamInstantiator;
 import org.objenesis.instantiator.gcj.GCJInstantiator;
-import org.objenesis.instantiator.jrockit.JRockit131Instantiator;
-import org.objenesis.instantiator.jrockit.JRockitLegacyInstantiator;
 import org.objenesis.instantiator.perc.PercInstantiator;
-import org.objenesis.instantiator.sun.Sun13Instantiator;
 import org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator;
+import org.objenesis.instantiator.sun.UnsafeFactoryInstantiator;
+
+import java.io.Serializable;
+
+import static org.objenesis.strategy.PlatformDescription.*;
 
 /**
  * Guess the best instantiator for a given class. The instantiator will instantiate the class
@@ -34,7 +40,7 @@
  * <li>JVM vendor version</li>
  * </ul>
  * However, instantiators are stateful and so dedicated to their class.
- * 
+ *
  * @author Henri Tremblay
  * @see ObjectInstantiator
  */
@@ -43,49 +49,52 @@
    /**
     * Return an {@link ObjectInstantiator} allowing to create instance without any constructor being
     * called.
-    * 
+    *
     * @param type Class to instantiate
     * @return The ObjectInstantiator for the class
     */
-   public ObjectInstantiator newInstantiatorOf(Class type) {
+   public <T> ObjectInstantiator<T> newInstantiatorOf(Class<T> type) {
 
-      if(JVM_NAME.startsWith(SUN)) {
-         if(VM_VERSION.startsWith("1.3")) {
-            return new Sun13Instantiator(type);
-         }
-      }
-      else if(JVM_NAME.startsWith(JROCKIT)) {
-         if(VM_VERSION.startsWith("1.3")) {
-            return new JRockit131Instantiator(type);
-         }
-         else if(VM_VERSION.startsWith("1.4")) {
-            // JRockit vendor version will be RXX where XX is the version
-            // Versions prior to 26 need special handling
-            // From R26 on, java.vm.version starts with R
-            if(!VENDOR_VERSION.startsWith("R")) {
-               // On R25.1 and R25.2, ReflectionFactory should work. Otherwise, we must use the
-               // Legacy instantiator.
-               if(VM_INFO == null || !VM_INFO.startsWith("R25.1") || !VM_INFO.startsWith("R25.2")) {
-                  return new JRockitLegacyInstantiator(type);
-               }
+      if(PlatformDescription.isThisJVM(HOTSPOT) || PlatformDescription.isThisJVM(OPENJDK)) {
+         if(PlatformDescription.isGoogleAppEngine()) {
+            if(Serializable.class.isAssignableFrom(type)) {
+               return new ObjectInputStreamInstantiator<T>(type);
             }
+            return new AccessibleInstantiator<T>(type);
          }
+         // The UnsafeFactoryInstantiator would also work. But according to benchmarks, it is 2.5
+         // times slower. So I prefer to use this one
+         return new SunReflectionFactoryInstantiator<T>(type);
       }
-      else if(JVM_NAME.startsWith(DALVIK)) {
-         return new AndroidInstantiator(type);
+      else if(PlatformDescription.isThisJVM(DALVIK)) {
+         if(PlatformDescription.isAndroidOpenJDK()) {
+            // Starting at Android N which is based on OpenJDK
+            return new UnsafeFactoryInstantiator<T>(type);
+         }
+         if(ANDROID_VERSION <= 10) {
+            // Android 2.3 Gingerbread and lower
+            return new Android10Instantiator<T>(type);
+         }
+         if(ANDROID_VERSION <= 17) {
+            // Android 3.0 Honeycomb to 4.2 Jelly Bean
+            return new Android17Instantiator<T>(type);
+         }
+         // Android 4.3 until Android N
+         return new Android18Instantiator<T>(type);
       }
-      else if(JVM_NAME.startsWith(GNU)) {
-         return new GCJInstantiator(type);
+      else if(PlatformDescription.isThisJVM(JROCKIT)) {
+         // JRockit is compliant with HotSpot
+         return new SunReflectionFactoryInstantiator<T>(type);
       }
-      else if(JVM_NAME.startsWith(PERC)) {
-    	  return new PercInstantiator(type);
+      else if(PlatformDescription.isThisJVM(GNU)) {
+         return new GCJInstantiator<T>(type);
+      }
+      else if(PlatformDescription.isThisJVM(PERC)) {
+         return new PercInstantiator<T>(type);
       }
 
-      // Fallback instantiator, should work with:
-      // - Java Hotspot version 1.4 and higher
-      // - JRockit 1.4-R26 and higher
-      // - IBM and Hitachi JVMs
-      // ... might works for others so we just give it a try
-      return new SunReflectionFactoryInstantiator(type);
+      // Fallback instantiator, should work with most modern JVM
+      return new UnsafeFactoryInstantiator<T>(type);
+
    }
 }
diff --git a/main/src/main/java/org/objenesis/instantiator/NullInstantiator.java b/main/src/test/java/android/os/Build.java
similarity index 66%
rename from main/src/main/java/org/objenesis/instantiator/NullInstantiator.java
rename to main/src/test/java/android/os/Build.java
index ab2a44f..c4b3107 100644
--- a/main/src/main/java/org/objenesis/instantiator/NullInstantiator.java
+++ b/main/src/test/java/android/os/Build.java
@@ -1,31 +1,29 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator;

-

-/**

- * The instantiator that always return a null instance

- * 

- * @author Henri Tremblay

- */

-public class NullInstantiator implements ObjectInstantiator {

-

-   /**

-    * @return Always null

-    */

-   public Object newInstance() {

-      return null;

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+/**
+ * Mimics the real Android class. Used for testing
+ * 
+ * @author Henri Tremblay
+ */
+public class Build {
+
+   public static class VERSION {
+      public static final int SDK_INT = 42;
+      public static final String SDK = "42";
+   }
+}
diff --git a/main/src/test/java/org/objenesis/ClassReader.java b/main/src/test/java/org/objenesis/ClassReader.java
new file mode 100644
index 0000000..21dbb1d
--- /dev/null
+++ b/main/src/test/java/org/objenesis/ClassReader.java
@@ -0,0 +1,340 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+import static org.junit.Assert.*;
+import static org.objenesis.instantiator.basic.ClassDefinitionUtils.*;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ClassReader {
+
+   byte[] buffer = new byte[256];
+   Object[] constant_pool;
+
+   public static void main(String[] args) throws IOException {
+      if(args.length != 1) {
+         System.out.println("Usage: ClassReader (path_to_the_class_file|class:complete_class_name)");
+      }
+
+      ClassReader reader = new ClassReader();
+      reader.readClass(args[0]);
+   }
+
+   static class CONSTANT_Utf8_info {
+      // int length; u2 is read by readUTF
+      String bytes;
+
+      CONSTANT_Utf8_info(DataInputStream in) throws IOException {
+         bytes = in.readUTF();
+      }
+
+      @Override
+      public String toString() {
+         return "CONSTANT_Utf8_info{" +
+            "bytes='" + bytes + '\'' +
+            '}';
+      }
+   }
+
+   static class CONSTANT_Methodref_info {
+      int class_index; // u2
+      int name_and_type_index; // u2
+
+      CONSTANT_Methodref_info(DataInputStream in) throws IOException {
+         class_index = in.readUnsignedShort();
+         name_and_type_index = in.readUnsignedShort();
+      }
+
+      @Override
+      public String toString() {
+         return "CONSTANT_Methodref_info{" +
+            "class_index=" + class_index +
+            ", name_and_type_index=" + name_and_type_index +
+            '}';
+      }
+   }
+
+   static class CONSTANT_Class_info {
+      int name_index; // u2
+
+      public CONSTANT_Class_info(DataInputStream in) throws IOException{
+         name_index = in.readUnsignedShort();
+      }
+
+      @Override
+      public String toString() {
+         return "CONSTANT_Class_info{" +
+            "name_index=" + name_index +
+            '}';
+      }
+   }
+
+   static class CONSTANT_NameAndType_info {
+      int name_index; // u2
+      int descriptor_index; // u2
+
+      public CONSTANT_NameAndType_info(DataInputStream in) throws IOException{
+         name_index = in.readUnsignedShort();
+         descriptor_index = in.readUnsignedShort();
+      }
+
+      @Override
+      public String toString() {
+         return "CONSTANT_NameAndType_info{" +
+            "name_index=" + name_index +
+            ", descriptor_index=" + descriptor_index +
+            '}';
+      }
+   }
+
+   class method_info {
+      int access_flags; // u2
+      int name_index;
+      int descriptor_index;
+      int attributes_count;
+      attribute_info[] attributes;
+
+      public method_info(DataInputStream in) throws IOException{
+         access_flags = in.readUnsignedShort();
+         name_index = in.readUnsignedShort();
+         descriptor_index = in.readUnsignedShort();
+         attributes_count = in.readUnsignedShort();
+         attributes = new attribute_info[attributes_count];
+
+         for (int i = 0; i < attributes_count; i++) {
+            attributes[i] = new attribute_info(in);
+         }
+      }
+
+      @Override
+      public String toString() {
+         return "method_info{" +
+            "access_flags=" + access_flags +
+            ", name_index=" + name_index +
+            ", descriptor_index=" + descriptor_index +
+            ", attributes_count=" + attributes_count +
+            '}';
+      }
+   }
+
+   class attribute_info {
+      int attribute_name_index; // u2
+      int attribute_length; // u4
+      Object info;
+
+      public attribute_info(DataInputStream in) throws IOException{
+         attribute_name_index = in.readUnsignedShort();
+         attribute_length = in.readInt();
+
+         String attribute_name = ((CONSTANT_Utf8_info) constant_pool[attribute_name_index]).bytes;
+
+         System.out.println(this +  " " + attribute_name);
+
+         if("Code".equals(attribute_name)) {
+            info = new Code_attribute(in);
+         }
+         else if("SourceFile".equals(attribute_name)) {
+            assertEquals(2, attribute_length); // always 2
+            info = new SourceFile_attribute(in);
+         }
+         else if("LineNumberTable".equals(attribute_name)) {
+            // I don't care about that (only used for debugging) so I will skip
+            System.out.println("Attribute LineNumberTable skipped");
+            in.read(buffer, 0, attribute_length);
+         }
+         else if("LocalVariableTable".equals(attribute_name)) {
+            // I don't care about that (only used for debugging) so I will skip
+            System.out.println("Attribute LocalVariableTable skipped");
+            in.read(buffer, 0, attribute_length);
+         }
+         else {
+            fail("Unknown attribute: " + attribute_name);
+         }
+
+         System.out.println("\t" + info);
+      }
+
+      @Override
+      public String toString() {
+         return "attribute_info{" +
+            "attribute_name_index=" + attribute_name_index +
+            ", attribute_length=" + attribute_length +
+            '}';
+      }
+   }
+
+   class Code_attribute {
+      int max_stack; // u2
+      int max_locals; // u2
+      int code_length; // u4
+      byte[] code; // length of code_length
+      int exception_table_length; // u2 if will be 0, so we will skip the exception_table
+      int attributes_count; // u2
+      attribute_info[] attributes;
+
+      Code_attribute(DataInputStream in) throws IOException {
+         max_stack = in.readUnsignedShort();
+         max_locals = in.readUnsignedShort();
+         code_length = in.readInt();
+         code = new byte[code_length];
+         in.read(code);
+         exception_table_length = in.readUnsignedShort();
+         attributes_count = in.readUnsignedShort();
+         attributes = new attribute_info[attributes_count];
+         for (int i = 0; i < attributes_count; i++) {
+            attributes[i] = new attribute_info(in);
+         }
+      }
+
+      @Override
+      public String toString() {
+         return "Code_attribute{" +
+            "max_stack=" + max_stack +
+            ", max_locals=" + max_locals +
+            ", code_length=" + code_length +
+            ", code=" + Arrays.toString(code) +
+            ", exception_table_length=" + exception_table_length +
+            ", attributes_count=" + attributes_count +
+            '}';
+      }
+   }
+
+   static class SourceFile_attribute {
+      int sourcefile_index;
+
+      SourceFile_attribute(DataInputStream in) throws IOException {
+         sourcefile_index = in.readUnsignedShort();
+      }
+
+      @Override
+      public String toString() {
+         return "SourceFile_attribute{" +
+            "sourcefile_index=" + sourcefile_index +
+            '}';
+      }
+   }
+
+   public void readClass(String classPath) throws IOException {
+      InputStream iin;
+      if(classPath.startsWith("classpath:")) {
+         String className = classPath.substring("classpath:".length());
+         String resourceName = classNameToResource(className);
+         iin = getClass().getClassLoader().getResourceAsStream(resourceName);
+      }
+      else {
+         iin = new FileInputStream(classPath);
+      }
+
+      DataInputStream in = new DataInputStream(iin);
+
+      // magic number
+      in.read(buffer, 0, MAGIC.length);
+      assertArrayEquals(MAGIC);
+
+      // version
+      in.read(buffer, 0, VERSION.length);
+      assertArrayEquals(VERSION);
+
+      // constant_pool_count
+      int constant_pool_count = in.readUnsignedShort();
+      System.out.println("Constant pool count: " + constant_pool_count);
+
+      // indexed from 1 (0 will be unused) to constant_pool_count-1
+      constant_pool = new Object[constant_pool_count];
+
+      // constant pool
+      for (int i = 1; i < constant_pool_count; i++) {
+         System.out.print(i + ": ");
+         int type = in.readUnsignedByte();
+         switch(type) {
+         case CONSTANT_Utf8:
+            constant_pool[i] = new CONSTANT_Utf8_info(in);
+            break;
+         case CONSTANT_Class:
+            constant_pool[i] = new CONSTANT_Class_info(in);
+            break;
+         case CONSTANT_Methodref:
+            constant_pool[i] = new CONSTANT_Methodref_info(in);
+            break;
+         case CONSTANT_NameAndType:
+            constant_pool[i] = new CONSTANT_NameAndType_info(in);
+            break;
+         default:
+            fail("Unknown type: " + type);
+         }
+         System.out.println(constant_pool[i]);
+      }
+
+      // access flags
+      int access_flags = in.readUnsignedShort();
+      System.out.println("Access flags: " + access_flags); // see http://stackoverflow.com/questions/8949933/what-is-the-purpose-of-the-acc-super-access-flag-on-java-class-files
+
+      // this class name
+      int this_class = in.readUnsignedShort();
+      System.out.println("This class index: " + this_class);
+
+      // super class name
+      int super_class = in.readUnsignedShort();
+      System.out.println("This superclass index: " + super_class);
+
+      // interfaces implemented count (we have none)
+      int interfaces_count = in.readUnsignedShort();
+      System.out.println("Interfaces count: " + interfaces_count);
+      for (int i = 0; i < interfaces_count; i++) {
+         int index = in.readUnsignedShort();
+         System.out.println("Interface " + i + " index: " + index);
+      }
+
+      // fields count (we have none)
+      int fields_count = in.readUnsignedShort();
+      System.out.println("Fields count: " + fields_count);
+      assertEquals("Reading fields isn't yet supported", 0, fields_count);
+
+      //methods count (we have one)
+      int methods_count = in.readUnsignedShort();
+      System.out.println("Methods count: " + methods_count);
+
+      for (int i = 0; i < methods_count; i++) {
+         method_info methodInfo = new method_info(in);
+         System.out.println("for " + methodInfo);
+      }
+
+      // reading final class attributes
+      int attributes_count = in.readUnsignedShort();
+      System.out.println("Class attributes count: " + attributes_count);
+      for (int i = 0; i < attributes_count ; i++) {
+         attribute_info attributeInfo = new attribute_info(in);
+      }
+
+      in.close();
+   }
+
+   private void assertArrayEquals(byte[] expected) {
+      for (int i = 0; i < expected.length; i++) {
+         if(expected[i] != buffer[i]) {
+            fail("Expected was " + Arrays.toString(expected) + " but actual is " + Arrays.toString(buffer));
+         }
+      }
+   }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/NullInstantiator.java b/main/src/test/java/org/objenesis/EmptyClass.java
similarity index 66%
copy from main/src/main/java/org/objenesis/instantiator/NullInstantiator.java
copy to main/src/test/java/org/objenesis/EmptyClass.java
index ab2a44f..a7f71ef 100644
--- a/main/src/main/java/org/objenesis/instantiator/NullInstantiator.java
+++ b/main/src/test/java/org/objenesis/EmptyClass.java
@@ -1,31 +1,30 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator;

-

-/**

- * The instantiator that always return a null instance

- * 

- * @author Henri Tremblay

- */

-public class NullInstantiator implements ObjectInstantiator {

-

-   /**

-    * @return Always null

-    */

-   public Object newInstance() {

-      return null;

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import java.util.Date;
+
+/**
+ * Just used for testing. To see the bytecode of a really simple class
+ *
+ * @author Henri Tremblay
+ */
+public class EmptyClass extends Date {
+
+   public EmptyClass() {
+      throw new RuntimeException();
+   }
+}
diff --git a/main/src/test/java/org/objenesis/ExternalizableTest.java b/main/src/test/java/org/objenesis/ExternalizableTest.java
new file mode 100644
index 0000000..765bc45
--- /dev/null
+++ b/main/src/test/java/org/objenesis/ExternalizableTest.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import org.junit.Test;
+
+import java.io.*;
+import java.util.ArrayList;
+
+/**
+ * This test makes sure an issue mentioned is not occurring.
+ * @author Henri Tremblay
+ */
+public class ExternalizableTest {
+
+    public static class A extends ArrayList<String> implements Externalizable {
+
+        public A() {
+        }
+
+        public void writeExternal(ObjectOutput out) throws IOException {
+
+        }
+
+        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+
+        }
+    }
+
+    @Test
+    public void test() {
+        A a = ObjenesisHelper.newSerializableInstance(A.class);
+        // This call should work because the ArrayList constructor as been called. This is required by A implementing Externalizable
+        a.add("Test");
+    }
+}
diff --git a/main/src/test/java/org/objenesis/ObjenesisExceptionTest.java b/main/src/test/java/org/objenesis/ObjenesisExceptionTest.java
index 407a2fd..a49dea5 100644
--- a/main/src/test/java/org/objenesis/ObjenesisExceptionTest.java
+++ b/main/src/test/java/org/objenesis/ObjenesisExceptionTest.java
@@ -1,54 +1,59 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis;

-

-import junit.framework.TestCase;

-

-/**

- * @author Henri Tremblay

- */

-public class ObjenesisExceptionTest extends TestCase {

-

-   public final void testObjenesisExceptionString() {

-      Exception e = new ObjenesisException("test");

-      assertEquals("test", e.getMessage());

-   }

-

-   public final void testObjenesisExceptionThrowable() {

-      Exception cause = new RuntimeException("test");

-      Exception e = new ObjenesisException(cause);

-      assertSame(cause, e.getCause());

-      assertEquals(cause.toString(), e.getMessage());

-

-      // Check null case

-      e = new ObjenesisException((Throwable) null);

-      assertNull(e.getCause());

-      assertEquals(null, e.getMessage());

-   }

-

-   public final void testObjenesisExceptionStringThrowable() {

-      Exception cause = new RuntimeException("test");

-      Exception e = new ObjenesisException("msg", cause);

-      assertSame(cause, e.getCause());

-      assertEquals("msg", e.getMessage());

-

-      // Check null case

-      e = new ObjenesisException("test", null);

-      assertNull(e.getCause());

-      assertEquals("test", e.getMessage());

-   }

-

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ObjenesisExceptionTest {
+
+   @Test
+   public final void testObjenesisExceptionString() {
+      Exception e = new ObjenesisException("test");
+      assertEquals("test", e.getMessage());
+   }
+
+   @Test
+   public final void testObjenesisExceptionThrowable() {
+      Exception cause = new RuntimeException("test");
+      Exception e = new ObjenesisException(cause);
+      assertSame(cause, e.getCause());
+      assertEquals(cause.toString(), e.getMessage());
+
+      // Check null case
+      e = new ObjenesisException((Throwable) null);
+      assertNull(e.getCause());
+      assertEquals(null, e.getMessage());
+   }
+
+   @Test
+   public final void testObjenesisExceptionStringThrowable() {
+      Exception cause = new RuntimeException("test");
+      Exception e = new ObjenesisException("msg", cause);
+      assertSame(cause, e.getCause());
+      assertEquals("msg", e.getMessage());
+
+      // Check null case
+      e = new ObjenesisException("test", null);
+      assertNull(e.getCause());
+      assertEquals("test", e.getMessage());
+   }
+
+}
diff --git a/main/src/test/java/org/objenesis/ObjenesisTest.java b/main/src/test/java/org/objenesis/ObjenesisTest.java
index eddd4a8..111e639 100644
--- a/main/src/test/java/org/objenesis/ObjenesisTest.java
+++ b/main/src/test/java/org/objenesis/ObjenesisTest.java
@@ -1,72 +1,90 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis;

-

-import junit.framework.TestCase;

-

-import org.objenesis.instantiator.ObjectInstantiator;

-import org.objenesis.strategy.InstantiatorStrategy;

-

-/**

- * @author Henri Tremblay

- */

-public class ObjenesisTest extends TestCase {

-

-   public final void testObjenesis() {

-      Objenesis o = new ObjenesisStd();

-      assertEquals(

-         "org.objenesis.ObjenesisStd using org.objenesis.strategy.StdInstantiatorStrategy with caching",

-         o.toString());

-   }

-

-   public final void testObjenesis_WithoutCache() {

-      Objenesis o = new ObjenesisStd(false);

-      assertEquals(

-         "org.objenesis.ObjenesisStd using org.objenesis.strategy.StdInstantiatorStrategy without caching",

-         o.toString());

-

-      assertEquals(o.getInstantiatorOf(getClass()).newInstance().getClass(), getClass());

-   }

-

-   public final void testNewInstance() {

-      Objenesis o = new ObjenesisStd();

-      assertEquals(getClass(), o.newInstance(getClass()).getClass());

-   }

-

-   public final void testGetInstantiatorOf() {

-      Objenesis o = new ObjenesisStd();

-      ObjectInstantiator i1 = o.getInstantiatorOf(getClass());

-      // Test instance creation

-      assertEquals(getClass(), i1.newInstance().getClass());

-

-      // Test caching

-      ObjectInstantiator i2 = o.getInstantiatorOf(getClass());

-      assertSame(i1, i2);

-   }

-

-   public final void testToString() {

-      Objenesis o = new ObjenesisStd() {};

-      assertEquals(

-         "org.objenesis.ObjenesisTest$1 using org.objenesis.strategy.StdInstantiatorStrategy with caching",

-         o.toString());

-   }

-}

-

-class MyStrategy implements InstantiatorStrategy {

-   public ObjectInstantiator newInstantiatorOf(Class type) {

-      return null;

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.strategy.InstantiatorStrategy;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ObjenesisTest {
+
+   @Rule
+   public ExpectedException expectedException = ExpectedException.none();
+
+   @Test
+   public final void testObjenesis() {
+      Objenesis o = new ObjenesisStd();
+      assertEquals(
+         "org.objenesis.ObjenesisStd using org.objenesis.strategy.StdInstantiatorStrategy with caching",
+         o.toString());
+   }
+
+   @Test
+   public final void testObjenesis_WithoutCache() {
+      Objenesis o = new ObjenesisStd(false);
+      assertEquals(
+         "org.objenesis.ObjenesisStd using org.objenesis.strategy.StdInstantiatorStrategy without caching",
+         o.toString());
+
+      assertEquals(o.getInstantiatorOf(getClass()).newInstance().getClass(), getClass());
+   }
+
+   @Test
+   public final void testNewInstance() {
+      Objenesis o = new ObjenesisStd();
+      assertEquals(getClass(), o.newInstance(getClass()).getClass());
+   }
+
+   @Test
+   public final void testGetInstantiatorOf() {
+      Objenesis o = new ObjenesisStd();
+      ObjectInstantiator<?> i1 = o.getInstantiatorOf(getClass());
+      // Test instance creation
+      assertEquals(getClass(), i1.newInstance().getClass());
+
+      // Test caching
+      ObjectInstantiator<?> i2 = o.getInstantiatorOf(getClass());
+      assertSame(i1, i2);
+   }
+
+   @Test
+   public final void testGetInstantiatorOf_primitive() {
+      Objenesis o = new ObjenesisStd();
+      expectedException.expect(IllegalArgumentException.class);
+      o.getInstantiatorOf(long.class);
+   }
+
+   @Test
+   public final void testToString() {
+      Objenesis o = new ObjenesisStd() {};
+      assertEquals(
+         "org.objenesis.ObjenesisTest$1 using org.objenesis.strategy.StdInstantiatorStrategy with caching",
+         o.toString());
+   }
+}
+
+class MyStrategy implements InstantiatorStrategy {
+   public <T> ObjectInstantiator<T> newInstantiatorOf(Class<T> type) {
+      return null;
+   }
+}
diff --git a/main/src/test/java/org/objenesis/SerializingInstantiatorTest.java b/main/src/test/java/org/objenesis/SerializingInstantiatorTest.java
index 7eb5081..528cb6d 100644
--- a/main/src/test/java/org/objenesis/SerializingInstantiatorTest.java
+++ b/main/src/test/java/org/objenesis/SerializingInstantiatorTest.java
@@ -1,45 +1,40 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis;

-

-import java.io.NotSerializableException;

-

-import junit.framework.TestCase;

-

-/**

- * @author Henri Tremblay

- * @author Leonardo Mesquita

- */

-public class SerializingInstantiatorTest extends TestCase {

-

-   protected void setUp() throws Exception {

-      super.setUp();

-   }

-

-   protected void tearDown() throws Exception {

-      super.tearDown();

-   }

-

-   public void testNotSerializable() {

-      ObjenesisSerializer o = new ObjenesisSerializer();

-      try {

-    	  o.newInstance(Object.class);

-    	  fail("Should have thrown an exception");

-      } catch (ObjenesisException e) {

-    	  assertTrue(e.getCause() instanceof NotSerializableException);

-      }

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis;
+
+import static org.junit.Assert.*;
+
+import java.io.NotSerializableException;
+
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ * @author Leonardo Mesquita
+ */
+public class SerializingInstantiatorTest {
+
+   @Test
+   public void testNotSerializable() {
+      ObjenesisSerializer o = new ObjenesisSerializer();
+      try {
+    	  o.newInstance(Object.class);
+    	  fail("Should have thrown an exception");
+      } catch (ObjenesisException e) {
+    	  assertTrue(e.getCause() instanceof NotSerializableException);
+      }
+   }
+}
diff --git a/main/src/test/java/org/objenesis/instantiator/basic/ClassDefinitionUtilsTest.java b/main/src/test/java/org/objenesis/instantiator/basic/ClassDefinitionUtilsTest.java
new file mode 100644
index 0000000..50e01ca
--- /dev/null
+++ b/main/src/test/java/org/objenesis/instantiator/basic/ClassDefinitionUtilsTest.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.basic;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ClassDefinitionUtilsTest {
+
+   String className = "org.objenesis.EmptyClass";
+
+   @Test
+   public void testDefineClass() throws Exception {
+      byte[] b = ClassDefinitionUtils.readClass(className);
+      Class<?> c = ClassDefinitionUtils.defineClass(className, b, getClass().getClassLoader());
+      assertEquals(c.getName(), className);
+   }
+
+   @Test
+   public void testClassNameToInternalClassName() {
+      String actual = ClassDefinitionUtils.classNameToInternalClassName(className);
+      assertEquals("org/objenesis/EmptyClass", actual);
+   }
+
+   @Test
+   public void testClassNameToResource() {
+      String actual = ClassDefinitionUtils.classNameToResource(className);
+      assertEquals("org/objenesis/EmptyClass.class", actual);
+   }
+
+   @Test
+   public void testGetExistingClass_existing() {
+      Class<?> actual = ClassDefinitionUtils.getExistingClass(getClass().getClassLoader(),
+         getClass().getName());
+      assertSame(actual, getClass());
+   }
+
+   @Test
+   public void testGetExistingClass_notExisting() {
+      Class<?> actual = ClassDefinitionUtils.getExistingClass(getClass().getClassLoader(), getClass().getName() + "$$$1");
+      assertNull(actual);
+   }
+}
diff --git a/main/src/test/java/org/objenesis/instantiator/basic/ProxyingInstantiatorTest.java b/main/src/test/java/org/objenesis/instantiator/basic/ProxyingInstantiatorTest.java
new file mode 100644
index 0000000..7ccdffc
--- /dev/null
+++ b/main/src/test/java/org/objenesis/instantiator/basic/ProxyingInstantiatorTest.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.basic;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.objenesis.EmptyClass;
+import org.objenesis.instantiator.ObjectInstantiator;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Henri Tremblay
+ */
+@Ignore("Because it doesn't work without -Xverify:none")
+public class ProxyingInstantiatorTest {
+
+   @Test
+   public void testNewInstance() throws Exception {
+      ObjectInstantiator<EmptyClass> inst = new ProxyingInstantiator<EmptyClass>(EmptyClass.class);
+      EmptyClass c = inst.newInstance();
+      assertEquals("EmptyClass$$$Objenesis", c.getClass().getSimpleName());
+   }
+
+}
diff --git a/main/src/test/java/org/objenesis/instantiator/sun/MagicInstantiatorTest.java b/main/src/test/java/org/objenesis/instantiator/sun/MagicInstantiatorTest.java
new file mode 100644
index 0000000..ce11ced
--- /dev/null
+++ b/main/src/test/java/org/objenesis/instantiator/sun/MagicInstantiatorTest.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.instantiator.sun;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.objenesis.EmptyClass;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.strategy.PlatformDescription;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+/**
+ * @author Henri Tremblay
+ */
+public class MagicInstantiatorTest {
+
+   @Before
+   public void before() {
+      // I know it works one these two. Not sure on others
+      assumeTrue(
+         PlatformDescription.isThisJVM(PlatformDescription.HOTSPOT) ||
+            PlatformDescription.isThisJVM(PlatformDescription.OPENJDK));
+   }
+
+   @Test
+   public void testNewInstance() throws Exception {
+      ObjectInstantiator<EmptyClass> o1 = new MagicInstantiator<EmptyClass>(EmptyClass.class);
+      assertEquals(EmptyClass.class, o1.newInstance().getClass());
+
+      ObjectInstantiator<EmptyClass> o2 = new MagicInstantiator<EmptyClass>(EmptyClass.class);
+      assertEquals(EmptyClass.class, o2.newInstance().getClass());
+   }
+
+   @Test
+   public void testInternalInstantiator() {
+      ObjectInstantiator<EmptyClass> o1 = new MagicInstantiator<EmptyClass>(EmptyClass.class).getInstantiator();
+      assertEquals(EmptyClass.class, o1.newInstance().getClass());
+   }
+}
diff --git a/main/src/test/java/org/objenesis/strategy/PlatformDescriptionTest.java b/main/src/test/java/org/objenesis/strategy/PlatformDescriptionTest.java
new file mode 100644
index 0000000..22caca6
--- /dev/null
+++ b/main/src/test/java/org/objenesis/strategy/PlatformDescriptionTest.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.strategy;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.*;
+
+/**
+ * Currently the test just check nothing is crashing. A more complex test should play with class
+ * loading an properties
+ * 
+ * @author Henri Tremblay
+ */
+public class PlatformDescriptionTest {
+
+   @Test
+   public void isJvmName() {
+      PlatformDescription.isThisJVM(PlatformDescription.HOTSPOT);
+   }
+
+   @Test
+   public void test() {
+      if(!PlatformDescription.isThisJVM(PlatformDescription.DALVIK)) {
+         assertEquals(0, PlatformDescription.ANDROID_VERSION);
+      }
+   }
+
+   @Test
+   public void testAndroidVersion() throws Exception {
+      Method m = PlatformDescription.class.getDeclaredMethod("getAndroidVersion0");
+      m.setAccessible(true);
+      int actual = (Integer) m.invoke(null);
+      assertEquals(42, actual);
+   }
+}
diff --git a/tck-android/.settings/org.eclipse.jdt.core.prefs b/tck-android/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index abec6ca..0000000
--- a/tck-android/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,5 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.compliance=1.5
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.source=1.5
diff --git a/tck-android/AndroidManifest.xml b/tck-android/AndroidManifest.xml
index b17fbbc..61ef6af 100644
--- a/tck-android/AndroidManifest.xml
+++ b/tck-android/AndroidManifest.xml
@@ -1,21 +1,21 @@
 <?xml version="1.0" encoding="utf-8"?>
-
 <!--
-Copyright 2006-2013 the original author or authors.
 
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
+    Copyright 2006-2017 the original author or authors.
 
-    http://www.apache.org/licenses/LICENSE-2.0
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
 
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
 -->
-
 <!--
   Describes an Android application with a single Instrumentation,
   which runs the Objenesis TCK.
@@ -30,7 +30,7 @@
 
     <uses-sdk
         android:minSdkVersion="1"
-        android:targetSdkVersion="17" />
+        android:targetSdkVersion="25" />
 
     <application android:allowBackup="false">
         <uses-library android:name="android.test.runner" />
@@ -38,6 +38,9 @@
 
     <instrumentation
         android:name=".TckInstrumentation"
-        android:targetPackage="org.objenesis.tck.android">
-    </instrumentation>
-</manifest>
\ No newline at end of file
+        android:targetPackage="org.objenesis.tck.android" />
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="org.objenesis.tck.android"
+                     android:label="Objenesis Android TCK."/>
+</manifest>
diff --git a/tck-android/pom.xml b/tck-android/pom.xml
index abb64a1..46369e7 100644
--- a/tck-android/pom.xml
+++ b/tck-android/pom.xml
@@ -1,103 +1,146 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>

-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

-  <modelVersion>4.0.0</modelVersion>

-  <parent>

-    <groupId>org.objenesis</groupId>

-    <artifactId>objenesis-parent</artifactId>

-    <version>2.0-SNAPSHOT</version>

-  </parent>

-  <artifactId>objenesis-tck-android</artifactId>

-  <name>Objenesis Android TCK</name>

-  <description>Objenesis' TCK built for Android devices</description>

-  <packaging>apk</packaging>

-

-  <dependencies>

-    <dependency>

-      <groupId>org.objenesis</groupId>

-      <artifactId>objenesis-tck</artifactId>

-      <version>${project.version}</version>

-    </dependency>

-    <dependency>

-      <groupId>com.google.android</groupId>

-      <artifactId>android</artifactId>

-      <version>1.5_r3</version>

-      <scope>provided</scope>

-    </dependency>  

-  </dependencies>

-  <build>

-    <sourceDirectory>src</sourceDirectory>

-

-    <pluginManagement>

-      <plugins>

-        <plugin>

-          <groupId>com.jayway.maven.plugins.android.generation2</groupId>

-          <artifactId>android-maven-plugin</artifactId>

-          <version>3.5.0</version>

-          <extensions>true</extensions>

-        </plugin>

-      </plugins>

-    </pluginManagement>

-    <plugins>

-      <plugin>

-        <artifactId>maven-compiler-plugin</artifactId>

-        <configuration>

-          <source>1.5</source>

-          <target>1.5</target>

-        </configuration>

-      </plugin>

-        

-      <plugin>

-        <groupId>com.jayway.maven.plugins.android.generation2</groupId>

-        <artifactId>android-maven-plugin</artifactId>

-        <configuration>

-          <sdk>

-            <platform>17</platform>

-          </sdk>

-        </configuration>

-        <extensions>true</extensions>

-      </plugin>

-      

-      <plugin>

-        <groupId>org.codehaus.mojo</groupId>

-        <artifactId>exec-maven-plugin</artifactId>

-        <version>1.2.1</version>

-        <inherited>false</inherited>

-        <executions>

-          <execution>

-            <id>install</id>

-            <phase>integration-test</phase>

-            <goals>

-              <goal>exec</goal>

-            </goals>

-            <configuration>

-              <executable>adb</executable>

-              <arguments>

-                <argument>install</argument>

-                <argument>-r</argument>

-                <argument>${project.build.directory}\${project.build.finalName}.apk</argument>

-              </arguments>

-            </configuration>

-          </execution>

-          <execution>

-            <id>execute</id>

-            <phase>integration-test</phase>

-            <goals>

-              <goal>exec</goal>

-            </goals>

-            <configuration>

-              <executable>adb</executable>

-              <arguments>

-                <argument>shell</argument>

-                <argument>am</argument>

-                <argument>instrument</argument>

-                <argument>-w</argument>

-                <argument>org.objenesis.tck.android/.TckInstrumentation</argument>

-              </arguments>

-            </configuration>

-          </execution>          

-        </executions>

-      </plugin>      

-    </plugins>

-  </build>

-

-</project>

+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.objenesis</groupId>
+    <artifactId>objenesis-parent</artifactId>
+    <version>2.5</version>
+  </parent>
+  <artifactId>objenesis-tck-android</artifactId>
+  <name>Objenesis Android TCK</name>
+  <description>Objenesis' TCK built for Android devices</description>
+  <packaging>apk</packaging>
+
+  <properties>
+    <android.home>${env.ANDROID_HOME}</android.home>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.objenesis</groupId>
+      <artifactId>objenesis</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>objenesis-tck</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.android</groupId>
+      <artifactId>android</artifactId>
+      <version>4.1.1.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.android</groupId>
+      <artifactId>android-test</artifactId>
+      <version>4.1.1.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.hamcrest</groupId>
+          <artifactId>hamcrest-core</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>com.simpligility.maven.plugins</groupId>
+          <artifactId>android-maven-plugin</artifactId>
+          <version>4.4.3</version>
+          <extensions>true</extensions>
+          <configuration>
+            <testFailSafe>false</testFailSafe>
+            <test>
+              <instrumentationPackage>org.objenesis.tck.android</instrumentationPackage>
+              <instrumentationRunner>android.test.InstrumentationTestRunner</instrumentationRunner>
+            </test>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>com.keyboardsamurais.maven</groupId>
+        <artifactId>maven-timestamp-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>com.mycila.maven-license-plugin</groupId>
+        <artifactId>maven-license-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-remote-resources-plugin</artifactId>
+      </plugin>
+
+      <plugin>
+        <groupId>com.simpligility.maven.plugins</groupId>
+        <artifactId>android-maven-plugin</artifactId>
+        <configuration>
+          <sdk>
+            <platform>25</platform>
+          </sdk>
+        </configuration>
+        <extensions>true</extensions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <inherited>false</inherited>
+        <executions>
+          <execution>
+            <id>execute</id>
+            <phase>integration-test</phase>
+            <goals>
+              <goal>exec</goal>
+            </goals>
+            <configuration>
+              <executable>${android.home}/platform-tools/adb</executable>
+              <arguments>
+                <argument>shell</argument>
+                <argument>am</argument>
+                <argument>instrument</argument>
+                <argument>-w</argument>
+                <argument>org.objenesis.tck.android/.TckInstrumentation</argument>
+              </arguments>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+
+  </build>
+
+   <profiles>
+      <profile>
+         <!-- To activate in IntelliJ. This will allow compilation because it seems IntelliJ can't retrieve
+              the objenesis classes shaded in the objenesis-tck jar -->
+         <id>intellij-specific</id>
+         <dependencies>
+            <dependency>
+               <groupId>${project.groupId}</groupId>
+               <artifactId>objenesis</artifactId>
+               <version>${project.version}</version>
+            </dependency>
+         </dependencies>
+      </profile>
+   </profiles>
+</project>
diff --git a/tck-android/src/main/java/org/objenesis/tck/android/ObjenesisTest.java b/tck-android/src/main/java/org/objenesis/tck/android/ObjenesisTest.java
new file mode 100644
index 0000000..76d6d0d
--- /dev/null
+++ b/tck-android/src/main/java/org/objenesis/tck/android/ObjenesisTest.java
@@ -0,0 +1,92 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.tck.android;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Map;
+
+import org.objenesis.ObjenesisSerializer;
+import org.objenesis.ObjenesisStd;
+import org.objenesis.tck.Main;
+import org.objenesis.tck.Reporter;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Test case running the entire tck on android.
+ * 
+ * @author Henri Tremblay
+ */
+public class ObjenesisTest extends AndroidTestCase {
+
+   public static class JUnitReporter implements Reporter {
+
+      private String currentObjenesis;
+
+      private String currentCandidate;
+
+      public void startTests(String platformDescription, Map<String, Object> allCandidates,
+         Map<String, Object> allInstantiators) {
+      }
+
+      public void startTest(String candidateDescription, String objenesisDescription) {
+         currentCandidate = candidateDescription;
+         currentObjenesis = objenesisDescription;
+      }
+
+      public void endObjenesis(String description) {
+      }
+
+      public void endTests() {
+      }
+
+      public void exception(Exception exception) {
+         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+         PrintStream out = new PrintStream(buffer);
+         out.println("Exception when instantiating " + currentCandidate + " with "
+            + currentObjenesis + ": ");
+         exception.printStackTrace(out);
+         fail(buffer.toString());
+      }
+
+      public void result(boolean instantiatedObject) {
+         assertTrue("Instantiating " + currentCandidate + " with " + currentObjenesis + " failed",
+            instantiatedObject);
+      }
+
+      public void endTest() {
+      }
+   }
+
+   @SmallTest
+   public void testObjenesisStd() throws Exception {
+      Main.runStandardTest(new ObjenesisStd(), new JUnitReporter());
+   }
+
+   @SmallTest
+   public void testObjenesisSerializer() throws Exception {
+      Main.runSerializerTest(new ObjenesisSerializer(), new JUnitReporter());
+   }
+
+   @SmallTest
+   public void testObjenesisSerializerParentConstructorCalled() throws Exception {
+      boolean result = Main.runParentConstructorTest(new ObjenesisSerializer());
+      assertTrue(result);
+   }
+
+}
\ No newline at end of file
diff --git a/tck-android/src/main/java/org/objenesis/tck/android/TckInstrumentation.java b/tck-android/src/main/java/org/objenesis/tck/android/TckInstrumentation.java
index 23ee5cf..575b671 100644
--- a/tck-android/src/main/java/org/objenesis/tck/android/TckInstrumentation.java
+++ b/tck-android/src/main/java/org/objenesis/tck/android/TckInstrumentation.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,14 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.objenesis.tck.android;
 
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.os.Bundle;
-
 import org.objenesis.tck.Main;
+import org.objenesis.tck.TextReporter;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -33,21 +32,31 @@
  */
 public class TckInstrumentation extends Instrumentation {
 
+   @Override
    public void onCreate(Bundle arguments) {
       ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
       PrintStream printStream = new PrintStream(outputStream);
       System.setOut(printStream);
+      System.setErr(printStream);
 
       try {
-         Main.main(new String[0]);
+         launch();
       } catch (IOException e) {
          e.printStackTrace();
       }
-    
+
       Bundle bundle = new Bundle();
       String fromStdout = outputStream.toString();
       bundle.putString(Instrumentation.REPORT_KEY_STREAMRESULT, fromStdout);
       finish(Activity.RESULT_OK, bundle);
    }
-}
 
+   private void launch() throws IOException {
+      TextReporter reporter = new TextReporter(System.out, System.err);
+
+      boolean parentConstructorTestSuccessful = Main.run(reporter);
+
+      reporter.printResult(parentConstructorTestSuccessful);
+
+   }
+}
diff --git a/tck/.settings/org.eclipse.jdt.core.prefs b/tck/.settings/org.eclipse.jdt.core.prefs
index 302c5cb..0185411 100644
--- a/tck/.settings/org.eclipse.jdt.core.prefs
+++ b/tck/.settings/org.eclipse.jdt.core.prefs
@@ -1,296 +1,296 @@
-eclipse.preferences.version=1

-org.eclipse.jdt.core.codeComplete.argumentPrefixes=

-org.eclipse.jdt.core.codeComplete.argumentSuffixes=

-org.eclipse.jdt.core.codeComplete.fieldPrefixes=

-org.eclipse.jdt.core.codeComplete.fieldSuffixes=

-org.eclipse.jdt.core.codeComplete.localPrefixes=

-org.eclipse.jdt.core.codeComplete.localSuffixes=

-org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=

-org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=

-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.3

-org.eclipse.jdt.core.compiler.compliance=1.3

-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning

-org.eclipse.jdt.core.compiler.source=1.3

-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16

-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16

-org.eclipse.jdt.core.formatter.alignment_for_assignment=0

-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16

-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16

-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80

-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0

-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16

-org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0

-org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16

-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80

-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16

-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0

-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16

-org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16

-org.eclipse.jdt.core.formatter.blank_lines_after_imports=1

-org.eclipse.jdt.core.formatter.blank_lines_after_package=1

-org.eclipse.jdt.core.formatter.blank_lines_before_field=0

-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0

-org.eclipse.jdt.core.formatter.blank_lines_before_imports=1

-org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1

-org.eclipse.jdt.core.formatter.blank_lines_before_method=1

-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1

-org.eclipse.jdt.core.formatter.blank_lines_before_package=0

-org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1

-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1

-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line

-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line

-org.eclipse.jdt.core.formatter.comment.clear_blank_lines=true

-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true

-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true

-org.eclipse.jdt.core.formatter.comment.format_block_comments=true

-org.eclipse.jdt.core.formatter.comment.format_comments=true

-org.eclipse.jdt.core.formatter.comment.format_header=false

-org.eclipse.jdt.core.formatter.comment.format_html=true

-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true

-org.eclipse.jdt.core.formatter.comment.format_line_comments=true

-org.eclipse.jdt.core.formatter.comment.format_source_code=true

-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false

-org.eclipse.jdt.core.formatter.comment.indent_root_tags=true

-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert

-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert

-org.eclipse.jdt.core.formatter.comment.line_length=100

-org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true

-org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true

-org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false

-org.eclipse.jdt.core.formatter.compact_else_if=true

-org.eclipse.jdt.core.formatter.continuation_indentation=1

-org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=1

-org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off

-org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on

-org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false

-org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true

-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true

-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true

-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true

-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true

-org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true

-org.eclipse.jdt.core.formatter.indent_empty_lines=false

-org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true

-org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true

-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true

-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false

-org.eclipse.jdt.core.formatter.indentation.size=3

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert

-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert

-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert

-org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert

-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert

-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert

-org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert

-org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert

-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert

-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert

-org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert

-org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert

-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert

-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert

-org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert

-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert

-org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert

-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert

-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert

-org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert

-org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert

-org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert

-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert

-org.eclipse.jdt.core.formatter.join_lines_in_comments=true

-org.eclipse.jdt.core.formatter.join_wrapped_lines=true

-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false

-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false

-org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false

-org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false

-org.eclipse.jdt.core.formatter.lineSplit=100

-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false

-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false

-org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0

-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1

-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true

-org.eclipse.jdt.core.formatter.tabulation.char=space

-org.eclipse.jdt.core.formatter.tabulation.size=3

-org.eclipse.jdt.core.formatter.use_on_off_tags=false

-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false

-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true

-org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true

-org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=100
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=1
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=1
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=3
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=100
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=3
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/tck/.settings/org.eclipse.jdt.ui.prefs b/tck/.settings/org.eclipse.jdt.ui.prefs
index 7aaa343..0a73ed8 100644
--- a/tck/.settings/org.eclipse.jdt.ui.prefs
+++ b/tck/.settings/org.eclipse.jdt.ui.prefs
@@ -1,9 +1,62 @@
-eclipse.preferences.version=1

-formatter_profile=_Objenesis

-formatter_settings_version=12

-org.eclipse.jdt.ui.exception.name=e

-org.eclipse.jdt.ui.gettersetter.use.is=true

-org.eclipse.jdt.ui.javadoc=false

-org.eclipse.jdt.ui.keywordthis=false

-org.eclipse.jdt.ui.overrideannotation=true

-org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>

+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_Objenesis
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.javadoc=false
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/tck/pom.xml b/tck/pom.xml
index ba02bba..8a4992d 100644
--- a/tck/pom.xml
+++ b/tck/pom.xml
@@ -1,275 +1,168 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>

-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

-  <modelVersion>4.0.0</modelVersion>

-  <parent>

-    <groupId>org.objenesis</groupId>

-    <artifactId>objenesis-parent</artifactId>

-    <version>2.0-SNAPSHOT</version>

-  </parent>

-  <artifactId>objenesis-tck</artifactId>

-  

-  <name>Objenesis TCK</name>

-  <description>Objenesis' TCK</description>

-  <url>http://objenesis.org</url>  

-  

-  <properties>

-    <!-- These versions are also used to filter boot-bundles.properties -->

-    <log4j.version>1.2.17</log4j.version>

-    <spring.osgi.version>1.2.1</spring.osgi.version>

-    <slf4j.version>1.7.2</slf4j.version>  

-  </properties>

-

-  <dependencies>

-    <dependency>

-      <groupId>org.objenesis</groupId>

-      <artifactId>objenesis</artifactId>

-      <version>${project.version}</version>

-    </dependency>

-

-    <!-- Dependencies below are for the OSGi test -->

-  

-    <dependency>

-      <groupId>org.springframework.osgi</groupId>

-      <artifactId>spring-osgi-test</artifactId>

-      <version>${spring.osgi.version}</version>

-      <scope>test</scope>

-    </dependency>

-    <dependency>

-      <groupId>org.springframework.osgi</groupId>

-      <artifactId>spring-osgi-annotation</artifactId>

-      <version>${spring.osgi.version}</version>

-      <scope>test</scope>

-    </dependency>

-    <dependency>

-      <groupId>org.springframework.osgi</groupId>

-      <artifactId>spring-osgi-extender</artifactId>

-      <version>${spring.osgi.version}</version>

-      <scope>test</scope>

-    </dependency>

-    

-    <!-- These are just to have a nice logging -->

-    <dependency>

-      <groupId>org.slf4j</groupId>

-      <artifactId>jcl-over-slf4j</artifactId>

-      <version>${slf4j.version}</version>

-      <scope>test</scope>

-    </dependency>

-    <dependency>

-      <groupId>org.slf4j</groupId>

-      <artifactId>slf4j-api</artifactId>

-      <version>${slf4j.version}</version>

-      <scope>test</scope>

-    </dependency>

-    <dependency>

-      <groupId>org.slf4j</groupId>

-      <artifactId>slf4j-log4j12</artifactId>

-      <version>${slf4j.version}</version>

-      <scope>test</scope>

-    </dependency>

-    <dependency>

-      <groupId>log4j</groupId>

-      <artifactId>log4j</artifactId>

-      <version>${log4j.version}</version>

-      <scope>test</scope>

-    </dependency>

-    

-    <!-- And this is our Equinox implementation -->

-    <dependency>

-      <groupId>org.eclipse</groupId>

-      <artifactId>org.eclipse.osgi</artifactId>

-      <version>3.8.0.v20120529-1548</version>

-      <scope>test</scope>      

-    </dependency>    

-  </dependencies>

-  

-  <build>

-    <testResources>

-      <testResource>

-        <directory>test</directory>   

-        <filtering>true</filtering>

-      </testResource>

-    </testResources>  

-    <plugins>

-      <plugin>

-        <groupId>com.keyboardsamurais.maven</groupId>

-        <artifactId>maven-timestamp-plugin</artifactId>

-      </plugin>

-      <plugin>

-        <groupId>com.google.code.maven-license-plugin</groupId>

-        <artifactId>maven-license-plugin</artifactId>

-      </plugin>

-      <plugin>

-        <groupId>org.apache.maven.plugins</groupId>

-        <artifactId>maven-remote-resources-plugin</artifactId>

-      </plugin>

-      <plugin>

-        <groupId>org.apache.maven.plugins</groupId>

-        <artifactId>maven-jar-plugin</artifactId>

-        <configuration>

-          <archive>

-            <manifest>

-              <mainClass>org.objenesis.tck.Main</mainClass>

-            </manifest>

-          </archive>        

-        </configuration>

-      </plugin>       

-      <plugin>

-        <groupId>org.apache.maven.plugins</groupId>

-        <artifactId>maven-shade-plugin</artifactId>        

-        <version>1.6</version>

-        <executions>

-          <execution>

-            <phase>package</phase>

-            <goals>

-              <goal>shade</goal>

-            </goals>

-          </execution>

-        </executions>

-      </plugin> 

-      <plugin>

-        <groupId>org.apache.maven.plugins</groupId>

-        <artifactId>maven-javadoc-plugin</artifactId>

-        <configuration>

-          <links>

-            <link>http://objenesis.googlecode.com/svn/docs/apidocs/</link>

-          </links>

-        </configuration>

-      </plugin>      

-    </plugins>

-  </build>

-

-  <profiles>

-    <profile>

-      <id>jvm-test</id>

-      <build>

-        <plugins>

-          <plugin>

-            <artifactId>maven-surefire-plugin</artifactId>

-            <executions>

-              <execution>

-                <id>Sun 1.3</id>

-                <goals>

-                  <goal>test</goal>

-                </goals>

-                <phase>test</phase>

-                <configuration>

-                  <jvm>${sun_jdk1_3.jvm}</jvm>

-                </configuration>

-              </execution>

-              <execution>

-                <id>Sun 1.4</id>

-                <goals>

-                  <goal>test</goal>

-                </goals>

-                <phase>test</phase>

-                <configuration>

-                  <jvm>${sun_jdk1_4.jvm}</jvm>

-                </configuration>

-              </execution>

-              <execution>

-                <id>Sun 1.5</id>

-                <goals>

-                  <goal>test</goal>

-                </goals>

-                <phase>test</phase>

-                <configuration>

-                  <jvm>${sun_jdk1_5.jvm}</jvm>

-                </configuration>

-              </execution>

-              <execution>

-                <id>Sun 1.6</id>

-                <goals>

-                  <goal>test</goal>

-                </goals>

-                <phase>test</phase>

-                <configuration>

-                  <jvm>${sun_jdk1_6.jvm}</jvm>

-                </configuration>

-              </execution>

-              <execution>

-                <id>Sun 1.7</id>

-                <goals>

-                  <goal>test</goal>

-                </goals>

-                <phase>test</phase>

-                <configuration>

-                  <jvm>${sun_jdk1_7.jvm}</jvm>

-                </configuration>

-              </execution>

-              <execution>

-                <id>JRockit for Java 1.3</id>

-                <goals>

-                  <goal>test</goal>

-                </goals>

-                <phase>test</phase>

-                <configuration>

-                  <jvm>${jrockit1_3.jvm}</jvm>

-                </configuration>

-              </execution>

-              <execution>

-                <id>JRockit for Java 1.4</id>

-                <goals>

-                  <goal>test</goal>

-                </goals>

-                <phase>test</phase>

-                <configuration>

-                  <jvm>${jrockit1_4.jvm}</jvm>

-                </configuration>

-              </execution>

-              <execution>

-                <id>JRockit for Java 1.5</id>

-                <goals>

-                  <goal>test</goal>

-                </goals>

-                <phase>test</phase>

-                <configuration>

-                  <jvm>${jrockit1_5.jvm}</jvm>

-                </configuration>

-              </execution>

-              <execution>

-                <id>JRockit for Java 1.6</id>

-                <goals>

-                  <goal>test</goal>

-                </goals>

-                <phase>test</phase>

-                <configuration>

-                  <jvm>${jrockit1_6.jvm}</jvm>

-                </configuration>

-              </execution>

-            </executions>

-          </plugin>

-        </plugins>

-      </build>

-    </profile>

-    <profile>

-      <!-- Activate to create a complete release -->

-      <id>release</id>

-      <build>

-        <plugins>

-          <plugin>

-            <groupId>org.codehaus.mojo</groupId>

-            <artifactId>exec-maven-plugin</artifactId>

-            <version>1.2.1</version>

-            <inherited>false</inherited>

-            <configuration>

-              <executable>java</executable>

-              <arguments>

-                <argument>-jar</argument>

-                <argument>${project.build.directory}\${project.build.finalName}.jar</argument>

-              </arguments>

-            </configuration>

-            <executions>

-              <execution>

-                <id>test-release</id>

-                <phase>integration-test</phase>

-                <goals>

-                  <goal>exec</goal>

-                </goals>

-              </execution>

-            </executions>

-          </plugin>

-        </plugins>

-      </build>

-    </profile>    

-  </profiles>

-</project>

+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.objenesis</groupId>
+    <artifactId>objenesis-parent</artifactId>
+    <version>2.5</version>
+  </parent>
+  <artifactId>objenesis-tck</artifactId>
+
+  <name>Objenesis TCK</name>
+  <description>Objenesis' TCK</description>
+  <url>http://objenesis.org</url>
+
+  <properties>
+    <paxexam.version>3.5.0</paxexam.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.objenesis</groupId>
+      <artifactId>objenesis</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <!-- Dependencies below are for the OSGi test -->
+
+    <dependency>
+      <groupId>org.ops4j.pax.exam</groupId>
+      <artifactId>pax-exam-junit4</artifactId>
+      <version>${paxexam.version}</version>
+      <scope>test</scope>
+      <exclusions>
+        <!-- Use the one bundled in Felix -->
+        <exclusion>
+          <groupId>org.osgi</groupId>
+          <artifactId>org.osgi.core</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>org.ops4j.pax.exam</groupId>
+      <artifactId>pax-exam-container-native</artifactId>
+      <version>${paxexam.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.ops4j.pax.exam</groupId>
+      <artifactId>pax-exam-link-mvn</artifactId>
+      <version>${paxexam.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- And this is our OSGi container -->
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.framework</artifactId>
+      <version>5.6.1</version>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- This is just to have a nice logging -->
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <version>1.1.7</version>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>com.keyboardsamurais.maven</groupId>
+        <artifactId>maven-timestamp-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>com.mycila.maven-license-plugin</groupId>
+        <artifactId>maven-license-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-remote-resources-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifest>
+              <mainClass>org.objenesis.tck.Main</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-shade-plugin</artifactId>
+        <configuration>
+          <createDependencyReducedPom>false</createDependencyReducedPom>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-javadoc-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>jvm-test</id>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>specific-jvm</id>
+                <goals>
+                  <goal>test</goal>
+                </goals>
+                <phase>test</phase>
+                <configuration>
+                  <jvm>${my.jvm}</jvm>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <!-- Activate to perform integration tests -->
+      <id>full</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>exec-maven-plugin</artifactId>
+            <inherited>false</inherited>
+            <configuration>
+              <executable>java</executable>
+              <arguments>
+                <argument>-jar</argument>
+                <argument>${project.build.directory}/${project.build.finalName}.jar</argument>
+              </arguments>
+            </configuration>
+            <executions>
+              <execution>
+                <id>test-release</id>
+                <phase>integration-test</phase>
+                <goals>
+                  <goal>exec</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/tck/src/main/java/org/objenesis/tck/CandidateLoader.java b/tck/src/main/java/org/objenesis/tck/CandidateLoader.java
index 294fd50..12f38b9 100644
--- a/tck/src/main/java/org/objenesis/tck/CandidateLoader.java
+++ b/tck/src/main/java/org/objenesis/tck/CandidateLoader.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,8 +21,9 @@
 import java.util.Properties;
 
 /**
- * Loads a set of candidate classes from a properties file into the TCK. <p/> The properties file
- * takes the form of candidateClassName=shortDescription.
+ * Loads a set of candidate classes from a properties file into the TCK.
+ * <p>
+ * The properties file takes the form of candidateClassName=shortDescription.
  * 
  * @author Joe Walnes
  * @see TCK
@@ -36,7 +37,7 @@
    /**
     * Handler for reporting errors from the CandidateLoader.
     */
-   public static interface ErrorHandler {
+   public interface ErrorHandler {
       /**
        * Called whenever, trying to retrieve a candidate class from its name, a
        * ClassNotFoundException is thrown
@@ -88,6 +89,7 @@
       // entries directly to the TCK (which retains order).
       Properties properties = new Properties() {
          private static final long serialVersionUID = 1L;
+         @Override
          public Object put(Object key, Object value) {
             handlePropertyEntry((String) key, (String) value);
             return null;
@@ -103,7 +105,7 @@
     * @param resource File name
     * @throws IOException If there's problem reading the file
     */
-   public void loadFromResource(Class cls, String resource) throws IOException {
+   public void loadFromResource(Class<?> cls, String resource) throws IOException {
       InputStream candidatesConfig = cls.getResourceAsStream(resource);
       if(candidatesConfig == null) {
          throw new IOException("Resource '" + resource + "' not found relative to " + cls.getName());
@@ -118,7 +120,7 @@
 
    private void handlePropertyEntry(String key, String value) {
       try {
-         Class candidate = Class.forName(key, true, classloader);
+         Class<?> candidate = Class.forName(key, true, classloader);
          tck.registerCandidate(candidate, value);
       }
       catch(ClassNotFoundException e) {
diff --git a/tck/src/main/java/org/objenesis/tck/Main.java b/tck/src/main/java/org/objenesis/tck/Main.java
index 8634cfb..3c6b02b 100644
--- a/tck/src/main/java/org/objenesis/tck/Main.java
+++ b/tck/src/main/java/org/objenesis/tck/Main.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,16 +15,16 @@
  */
 package org.objenesis.tck;
 
-import java.io.IOException;
-import java.io.Serializable;
-
 import org.objenesis.Objenesis;
 import org.objenesis.ObjenesisSerializer;
 import org.objenesis.ObjenesisStd;
 
+import java.io.IOException;
+import java.io.Serializable;
+
 /**
  * Command line launcher for Technology Compatibility Kit (TCK).
- * 
+ *
  * @author Joe Walnes
  * @see TCK
  */
@@ -44,9 +44,10 @@
 
    private static class MockClass extends MockSuperClass implements Serializable {
       private static final long serialVersionUID = 1L;
-      
+
       private final boolean constructorCalled;
 
+      @SuppressWarnings("unused")
       public MockClass() {
          constructorCalled = true;
       }
@@ -58,7 +59,7 @@
 
    /**
     * Main class of the TCK. Can also be called as a normal method from an application server.
-    * 
+    *
     * @param args No parameters are required
     * @throws IOException When the TCK fails to read properties' files.
     */
@@ -66,37 +67,93 @@
 
       TextReporter reporter = new TextReporter(System.out, System.err);
 
-      runTest(new ObjenesisStd(), reporter, "Objenesis std", "candidates/candidates.properties");
-      runTest(new ObjenesisSerializer(), reporter, "Objenesis serializer",
-         "candidates/serializable-candidates.properties");
-
-      boolean result = runParentConstructorTest();
+      boolean result = run(reporter);
 
       reporter.printResult(result);
+
+      if(reporter.hasErrors()) {
+         System.exit(1);
+      }
    }
 
-   private static boolean runParentConstructorTest() {
+   /**
+    * Run the full test suite using standard Objenesis instances
+    *
+    * @param reporter result are recorded in the reporter
+    * @return if the parent constructor test was successful
+    */
+   public static boolean run(Reporter reporter) {
+      runStandardTest(new ObjenesisStd(), reporter);
+      runSerializerTest(new ObjenesisSerializer(), reporter);
+
+      boolean result = runParentConstructorTest(new ObjenesisSerializer());
+      return result;
+   }
+
+   /**
+    * Run the serializing suite on the provided Objenesis instance
+    *
+    * @param reporter result are recorded in the reporter
+    * @param objenesis Objenesis instance to test
+    */
+   public static void runSerializerTest(Objenesis objenesis, Reporter reporter) {
+      runTest(objenesis, reporter, "Objenesis serializer",
+         "candidates/serializable-candidates.properties");
+   }
+
+   /**
+    * Run the standard suite on the provided Objenesis instance
+    *
+    * @param reporter result are recorded in the reporter
+    * @param objenesis Objenesis instance to test
+    */
+   public static void runStandardTest(Objenesis objenesis, Reporter reporter) {
+      runTest(objenesis, reporter, "Objenesis std", "candidates/candidates.properties");
+   }
+
+   /**
+    * A special test making sure the first none serializable class no-args constructor is called
+    *
+    * @param objenesis Objenesis instance to test
+    * @return if the test was successful
+    */
+   public static boolean runParentConstructorTest(Objenesis objenesis) {
       try {
-         Object result = new ObjenesisSerializer().newInstance(MockClass.class);
+         Object result = objenesis.newInstance(MockClass.class);
          MockClass mockObject = (MockClass) result;
          return mockObject.isSuperConstructorCalled() && !mockObject.isConstructorCalled();
       }
       catch(Exception e) {
-         System.err.println("--- Not serializable parent constructor called ---");
+         System.err.println("--- Not serializable parent constructor called as expected ---");
          e.printStackTrace(System.err);
          return false;
       }
    }
 
-   private static void runTest(Objenesis objenesis, Reporter reporter, String description,
-      String candidates) throws IOException {
+   /**
+    * Run a suite of tests (candidates) on the Objenesis instance, sending the results to the
+    * reporter
+    *
+    * @param objenesis Objenesis instance to test
+    * @param reporter result are recorded in the reporter
+    * @param description description of the ran suite
+    * @param candidates property file containing a list of classes to test (key) and their
+    *        description (value)
+    */
+   public static void runTest(Objenesis objenesis, Reporter reporter, String description,
+      String candidates) {
       TCK tck = new TCK();
       tck.registerObjenesisInstance(objenesis, description);
 
       CandidateLoader candidateLoader = new CandidateLoader(tck, Main.class.getClassLoader(),
          new CandidateLoader.LoggingErrorHandler(System.err));
 
-      candidateLoader.loadFromResource(Main.class, candidates);
+      try {
+         candidateLoader.loadFromResource(Main.class, candidates);
+      }
+      catch(IOException e) {
+         throw new RuntimeException(e);
+      }
 
       tck.runTests(reporter);
    }
diff --git a/tck/src/main/java/org/objenesis/tck/Reporter.java b/tck/src/main/java/org/objenesis/tck/Reporter.java
index a73783d..7217da0 100644
--- a/tck/src/main/java/org/objenesis/tck/Reporter.java
+++ b/tck/src/main/java/org/objenesis/tck/Reporter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 package org.objenesis.tck;
 
-import java.util.Collection;
+import java.util.Map;
 
 /**
  * Reports results from the TCK back to the user.
@@ -38,11 +38,12 @@
     * 
     * @param platformDescription Description the platform being run on (i.e. JVM version, vendor,
     *        etc).
-    * @param allCandidates Descriptions (String) of all candidates being used in tests.
-    * @param allObjenesisInstances Descriptions of all Objenesis instances being used in tests.
+    * @param allCandidates Descriptions (String) of all candidates (Object) being used in tests.
+    * @param allObjenesisInstances Descriptions (String) of all Objenesis instances (Object) being
+    *        used in tests.
     */
-   void startTests(String platformDescription, Collection allCandidates,
-      Collection allObjenesisInstances);
+   void startTests(String platformDescription, Map<String, Object> allCandidates,
+      Map<String, Object> allObjenesisInstances);
 
    /**
     * Report that a test between a candidate and an objenesis instance if about to start.
diff --git a/tck/src/main/java/org/objenesis/tck/TCK.java b/tck/src/main/java/org/objenesis/tck/TCK.java
index 00046e2..4f93b25 100644
--- a/tck/src/main/java/org/objenesis/tck/TCK.java
+++ b/tck/src/main/java/org/objenesis/tck/TCK.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,21 +15,21 @@
  */
 package org.objenesis.tck;
 
+import org.objenesis.Objenesis;
+import org.objenesis.strategy.PlatformDescription;
+
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import org.objenesis.Objenesis;
-
 /**
  * <b>Technology Compatibility Kit</b> (TCK) for {@link Objenesis}s.
- * <p/>
+ * <p>
  * This TCK accepts a set of candidate classes (class it attempts to instantiate) and a set of
  * Objenesis implementations. It then tries instantiating every candidate with every Objenesis
  * implementations, reporting the results to a {@link Reporter}.
+ * 
  * <h3>Example usage</h3>
  * 
  * <pre>
@@ -53,9 +53,9 @@
  */
 public class TCK {
 
-   private final List objenesisInstances = new ArrayList();
-   private final List candidates = new ArrayList();
-   private final Map descriptions = new HashMap();
+   private final List<Objenesis> objenesisInstances = new ArrayList<Objenesis>();
+   private final List<Class<?>> candidates = new ArrayList<Class<?>>();
+   private final Map<Object, String> descriptions = new HashMap<Object, String>();
 
    /**
     * Register a candidate class to attempt to instantiate.
@@ -63,7 +63,7 @@
     * @param candidateClass Class to attempt to instantiate
     * @param description Description of the class
     */
-   public void registerCandidate(Class candidateClass, String description) {
+   public void registerCandidate(Class<?> candidateClass, String description) {
       candidates.add(candidateClass);
       descriptions.put(candidateClass, description);
    }
@@ -86,20 +86,17 @@
     */
    public void runTests(Reporter reporter) {
       reporter.startTests(describePlatform(), findAllDescriptions(candidates, descriptions),
-         findAllDescriptions(objenesisInstances, descriptions));
+              findAllDescriptions(objenesisInstances, descriptions));
 
-      for(Iterator i = candidates.iterator(); i.hasNext();) {
-         Class candidateClass = (Class) i.next();
-         String candidateDescription = (String) descriptions.get(candidateClass);
+      for(Class<?> candidateClass : candidates) {
+         String candidateDescription = descriptions.get(candidateClass);
 
-         for(Iterator j = objenesisInstances.iterator(); j.hasNext();) {
-            Objenesis objenesis = (Objenesis) j.next();
-
-            String objenesisDescription = (String) descriptions.get(objenesis);
+         for(Objenesis objenesis : objenesisInstances) {
+            String objenesisDescription = descriptions.get(objenesis);
 
             reporter.startTest(candidateDescription, objenesisDescription);
 
-            runTest(reporter, candidateClass, objenesis, candidateDescription);
+            runTest(reporter, candidateClass, objenesis);
 
             reporter.endTest();
          }
@@ -107,8 +104,7 @@
       reporter.endTests();
    }
 
-   private void runTest(Reporter reporter, Class candidate, Objenesis objenesis,
-      String candidateDescription) {
+   private void runTest(Reporter reporter, Class<?> candidate, Objenesis objenesis) {
       try {
          Object instance = objenesis.newInstance(candidate);
          boolean success = instance != null && instance.getClass() == candidate;
@@ -119,10 +115,19 @@
       }
    }
 
-   private Collection findAllDescriptions(List keys, Map descriptions) {
-      List results = new ArrayList(keys.size());
-      for(int i = 0; i < keys.size(); i++) {
-         results.add(descriptions.get(keys.get(i)));
+   /**
+    * Return the human readable description for list of TCK items (Objenesis instances or test
+    * candidates)
+    * 
+    * @param keys list of items for which we are searching for a description
+    * @param descriptions all descriptions
+    * @return map of items with their description. Will contain one entry per entry in the original
+    *         key list
+    */
+   private Map<String, Object> findAllDescriptions(List<?> keys, Map<?, String> descriptions) {
+      Map<String, Object> results = new HashMap<String, Object>(keys.size());
+      for(Object o : keys) {
+         results.put(descriptions.get(o), o);
       }
       return results;
    }
@@ -130,14 +135,11 @@
    /**
     * Describes the platform. Outputs Java version and vendor. To change this behavior, override
     * this method.
-    * 
+    *
     * @return Description of the current platform
     */
    protected String describePlatform() {
-      return "Java " + System.getProperty("java.specification.version") + " ("
-         + System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.name") + " "
-         + System.getProperty("java.vm.version") + " " + System.getProperty("java.runtime.version")
-         + ")";
+      return PlatformDescription.describePlatform();
    }
 
 }
diff --git a/tck/src/main/java/org/objenesis/tck/TextReporter.java b/tck/src/main/java/org/objenesis/tck/TextReporter.java
index f83c982..1c6b196 100644
--- a/tck/src/main/java/org/objenesis/tck/TextReporter.java
+++ b/tck/src/main/java/org/objenesis/tck/TextReporter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,21 +15,16 @@
  */
 package org.objenesis.tck;
 
+import org.objenesis.Objenesis;
+
 import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
+import java.util.*;
 
 /**
  * Reports results from TCK as tabulated text, suitable for dumping to the console or a file and
- * being read by a human. If can be reused to provide a summary reports of different candidates as
- * long as the same objenesisDescription is not used twice.
- * 
+ * being read by a human. It can be reused to provide a summary reports of different candidates as
+ * long as the same <code>objenesisDescription</code> is not used twice.
+ *
  * @author Joe Walnes
  * @author Henri Tremblay
  * @see TCK
@@ -72,15 +67,15 @@
 
    private int errorCount = 0;
 
-   private SortedSet allCandidates = new TreeSet();
+   private SortedMap<String, Object> allCandidates = new TreeMap<String, Object>();
 
-   private SortedSet allInstantiators = new TreeSet();
+   private SortedMap<String, Object> allInstantiators = new TreeMap<String, Object>();
 
    private String currentObjenesis;
 
    private String currentCandidate;
 
-   private Map objenesisResults = new HashMap();
+   private Map<Object, Map<String, Result>> objenesisResults = new HashMap<Object, Map<String, Result>>();
 
    private String platformDescription;
 
@@ -93,18 +88,21 @@
       this.log = log;
    }
 
-   public void startTests(String platformDescription, Collection allCandidates,
-      Collection allInstantiators) {
+   public int getErrorCount() {
+      return errorCount;
+   }
+
+   public void startTests(String platformDescription, Map<String, Object> allCandidates,
+      Map<String, Object> allInstantiators) {
 
       // HT: in case the same reporter is reused, I'm guessing that it will
-      // always be the
-      // same platform
+      // always be the same platform
       this.platformDescription = platformDescription;
-      this.allCandidates.addAll(allCandidates);
-      this.allInstantiators.addAll(allInstantiators);
+      this.allCandidates.putAll(allCandidates);
+      this.allInstantiators.putAll(allInstantiators);
 
-      for(Iterator it = allInstantiators.iterator(); it.hasNext();) {
-         objenesisResults.put(it.next(), new HashMap());
+      for(String desc : allInstantiators.keySet()) {
+         objenesisResults.put(desc, new HashMap<String, Result>());
       }
 
       startTime = System.currentTimeMillis();
@@ -119,7 +117,8 @@
       if(!instantiatedObject) {
          errorCount++;
       }
-      ((Map) objenesisResults.get(currentObjenesis)).put(currentCandidate, new Result(
+      objenesisResults.get(currentObjenesis).put(currentCandidate,
+         new Result(
          currentObjenesis, currentCandidate, instantiatedObject, null));
    }
 
@@ -127,7 +126,8 @@
 
       errorCount++;
 
-      ((Map) objenesisResults.get(currentObjenesis)).put(currentCandidate, new Result(
+      objenesisResults.get(currentObjenesis).put(currentCandidate,
+         new Result(
          currentObjenesis, currentCandidate, false, exception));
    }
 
@@ -140,41 +140,53 @@
 
    /**
     * Print the final summary report
+    *
+    * @param parentConstructorTest If the test checking that the none serializable constructor was called was successful
     */
    public void printResult(boolean parentConstructorTest) {
       // Platform
       summary.println("Running TCK on platform: " + platformDescription);
       summary.println();
 
-      summary.println("Not serializable parent constructor called: "
+      // Instantiator implementations
+      summary.println("Instantiators used: ");
+      for(Map.Entry<String, Object> o : allInstantiators.entrySet()) {
+         String inst = ((Objenesis) o.getValue()).getInstantiatorOf(String.class).getClass()
+            .getSimpleName();
+         summary.println("   " + o.getKey() + ": " + inst);
+      }
+      summary.println();
+
+      // Parent constructor special test
+      summary.println("Not serializable parent constructor called as expected: "
          + (parentConstructorTest ? 'Y' : 'N'));
       summary.println();
-      
+
       if(!parentConstructorTest) {
          errorCount++;
       }
-      
-      int maxObjenesisWidth = lengthOfLongestStringIn(allInstantiators);
-      int maxCandidateWidth = lengthOfLongestStringIn(allCandidates);
 
-      // Header
+      Set<String> instantiators = this.allInstantiators.keySet();
+      Set<String> candidates = this.allCandidates.keySet();
+
+      int maxObjenesisWidth = lengthOfLongestStringIn(instantiators);
+      int maxCandidateWidth = lengthOfLongestStringIn(candidates);
+
+      // Strategy used
       summary.print(pad("", maxCandidateWidth) + ' ');
-      for(Iterator it = allInstantiators.iterator(); it.hasNext();) {
-         String desc = (String) it.next();
+      for(String desc : instantiators) {
          summary.print(pad(desc, maxObjenesisWidth) + ' ');
       }
       summary.println();
 
-      List exceptions = new ArrayList();
+      List<Result> exceptions = new ArrayList<Result>();
 
       // Candidates (and keep the exceptions meanwhile)
-      for(Iterator it = allCandidates.iterator(); it.hasNext();) {
-         String candidateDesc = (String) it.next();
+      for(String candidateDesc : candidates) {
          summary.print(pad(candidateDesc, maxCandidateWidth) + ' ');
 
-         for(Iterator itInst = allInstantiators.iterator(); itInst.hasNext();) {
-            String instDesc = (String) itInst.next();
-            Result result = (Result) ((Map) objenesisResults.get(instDesc)).get(candidateDesc);
+         for(String instDesc : instantiators) {
+            Result result = objenesisResults.get(instDesc).get(candidateDesc);
             if(result == null) {
                summary.print(pad("N/A", maxObjenesisWidth) + " ");
             }
@@ -194,8 +206,7 @@
       // Final
       if(errorCount != 0) {
 
-         for(Iterator it = exceptions.iterator(); it.hasNext();) {
-            Result element = (Result) it.next();
+         for(Result element : exceptions) {
             log.println("--- Candidate '" + element.candidateDescription + "', Instantiator '"
                + element.objenesisDescription + "' ---");
             element.exception.printStackTrace(log);
@@ -213,6 +224,15 @@
       summary.println();
    }
 
+   /**
+    * Return true if the reporter has registered some errors
+    *
+    * @return if there was errors during execution
+    */
+   public boolean hasErrors() {
+      return errorCount != 0;
+   }
+
    private String pad(String text, int width) {
       if(text.length() == width) {
          return text;
@@ -221,7 +241,7 @@
          return text.substring(0, width);
       }
       else {
-         StringBuffer padded = new StringBuffer(text);
+         StringBuilder padded = new StringBuilder(text);
          while(padded.length() < width) {
             padded.append(' ');
          }
@@ -229,10 +249,10 @@
       }
    }
 
-   private int lengthOfLongestStringIn(Collection descriptions) {
+   private int lengthOfLongestStringIn(Collection<String> descriptions) {
       int result = 0;
-      for(Iterator it = descriptions.iterator(); it.hasNext();) {
-         result = Math.max(result, ((String) it.next()).length());
+      for(Iterator<String> it = descriptions.iterator(); it.hasNext();) {
+         result = Math.max(result, it.next().length());
       }
       return result;
    }
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/ConstructorThrowingException.java b/tck/src/main/java/org/objenesis/tck/candidates/ConstructorThrowingException.java
index 43c3f7f..9f21909 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/ConstructorThrowingException.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/ConstructorThrowingException.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/ConstructorWithArguments.java b/tck/src/main/java/org/objenesis/tck/candidates/ConstructorWithArguments.java
index caebcf3..5e60265 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/ConstructorWithArguments.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/ConstructorWithArguments.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/ConstructorWithMandatoryArguments.java b/tck/src/main/java/org/objenesis/tck/candidates/ConstructorWithMandatoryArguments.java
index 52ae9c4..c8cab8e 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/ConstructorWithMandatoryArguments.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/ConstructorWithMandatoryArguments.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/DefaultPackageConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/DefaultPackageConstructor.java
index 7e05025..e66e6cf 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/DefaultPackageConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/DefaultPackageConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/DefaultPrivateConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/DefaultPrivateConstructor.java
index d84a0eb..f0d5ebf 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/DefaultPrivateConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/DefaultPrivateConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/DefaultProtectedConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/DefaultProtectedConstructor.java
index e3c665e..1254636 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/DefaultProtectedConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/DefaultProtectedConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/DefaultPublicConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/DefaultPublicConstructor.java
index da595f1..6d5222c 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/DefaultPublicConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/DefaultPublicConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/NoConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/NoConstructor.java
index df6ae4b..da1bc43 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/NoConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/NoConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorThrowingException.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorThrowingException.java
index 4eb3f82..d5a7027 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorThrowingException.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorThrowingException.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorWithArguments.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorWithArguments.java
index 88006dc..3113391 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorWithArguments.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorWithArguments.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorWithMandatoryArguments.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorWithMandatoryArguments.java
index e495576..931bc97 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorWithMandatoryArguments.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableConstructorWithMandatoryArguments.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPackageConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPackageConstructor.java
index 1147527..600fd81 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPackageConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPackageConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPrivateConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPrivateConstructor.java
index 2a93746..a908468 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPrivateConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPrivateConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultProtectedConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultProtectedConstructor.java
index bb2bc07..35545d5 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultProtectedConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultProtectedConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPublicConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPublicConstructor.java
index 0e1c356..b7bb71b 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPublicConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableDefaultPublicConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableNoConstructor.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableNoConstructor.java
index d9ee743..54157ff 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableNoConstructor.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableNoConstructor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableReplacer.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableReplacer.java
index ccfebbf..f887d21 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableReplacer.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableReplacer.java
@@ -1,30 +1,30 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.tck.candidates;

-

-import java.io.Serializable;

-

-/**

- * @author Joe Walnes

- */

-public class SerializableReplacer implements Serializable {

-   

-   private static final long serialVersionUID = 1L;

-   

-   protected Object writeReplace() {

-      return new SerializableResolver();

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.tck.candidates;
+
+import java.io.Serializable;
+
+/**
+ * @author Joe Walnes
+ */
+public class SerializableReplacer implements Serializable {
+   
+   private static final long serialVersionUID = 1L;
+   
+   protected Object writeReplace() {
+      return new SerializableResolver();
+   }
+}
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableResolver.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableResolver.java
index e5f01d4..7d6e766 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableResolver.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableResolver.java
@@ -1,30 +1,30 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.tck.candidates;

-

-import java.io.Serializable;

-

-/**

- * @author Joe Walnes

- */

-public class SerializableResolver implements Serializable {

-   

-   private static final long serialVersionUID = 1L;

-   

-   protected Object readResolve() {

-      return new SerializableReplacer();

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.tck.candidates;
+
+import java.io.Serializable;
+
+/**
+ * @author Joe Walnes
+ */
+public class SerializableResolver implements Serializable {
+   
+   private static final long serialVersionUID = 1L;
+   
+   protected Object readResolve() {
+      return new SerializableReplacer();
+   }
+}
diff --git a/tck/src/main/java/org/objenesis/tck/candidates/SerializableWithAncestorThrowingException.java b/tck/src/main/java/org/objenesis/tck/candidates/SerializableWithAncestorThrowingException.java
index 9a73f78..980e12a 100644
--- a/tck/src/main/java/org/objenesis/tck/candidates/SerializableWithAncestorThrowingException.java
+++ b/tck/src/main/java/org/objenesis/tck/candidates/SerializableWithAncestorThrowingException.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/tck/src/main/java/org/objenesis/tck/search/ClassEnumerator.java b/tck/src/main/java/org/objenesis/tck/search/ClassEnumerator.java
new file mode 100644
index 0000000..6de6d23
--- /dev/null
+++ b/tck/src/main/java/org/objenesis/tck/search/ClassEnumerator.java
@@ -0,0 +1,133 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.tck.search;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Taken and adapted from <a href="https://raw.githubusercontent.com/ddopson/java-class-enumerator/master/src/pro/ddopson/ClassEnumerator.java">here</a>
+ *
+ * @author Henri Tremblay
+ */
+public class ClassEnumerator {
+
+    private static void processDirectory(File directory, String pkgname, SortedSet<String> classes) {
+
+        // Get the list of the files contained in the package
+        String[] files = directory.list();
+
+        for (int i = 0; i < files.length; i++) {
+            String fileName = files[i];
+            // we are only interested in .class files
+            if (fileName.endsWith(".class")) {
+                // removes the .class extension
+                String className = pkgname + '.' + fileName.substring(0, fileName.length() - 6);
+                classes.add(className);
+                continue;
+            }
+
+            File subdir = new File(directory, fileName);
+            if (subdir.isDirectory()) {
+                processDirectory(subdir, pkgname + '.' + fileName, classes);
+            }
+        }
+    }
+
+    private static void processJarfile(URL resource, String pkgname, SortedSet<String> classes) {
+        String relPath = pkgname.replace('.', '/');
+        String resPath = resource.getPath();
+        String jarPath = resPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", "");
+
+        JarFile jarFile;
+        try {
+            jarFile = new JarFile(jarPath);
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected IOException reading JAR File '" + jarPath + "'", e);
+        }
+        Enumeration<JarEntry> entries = jarFile.entries();
+        while(entries.hasMoreElements()) {
+            JarEntry entry = entries.nextElement();
+            String entryName = entry.getName();
+            String className = null;
+            if(entryName.endsWith(".class") && entryName.startsWith(relPath) && entryName.length() > (relPath.length() + "/".length())) {
+                className = entryName.replace('/', '.').replace('\\', '.').replace(".class", "");
+            }
+
+            if (className != null) {
+                classes.add(className);
+            }
+        }
+    }
+
+   /**
+    * Return all the classes in this package recursively. The class loader of the {@code ClassEnumerator} class
+    * is used
+    *
+    * @param pkg the searched package
+    * @return list of full class names
+    */
+    public static SortedSet<String> getClassesForPackage(Package pkg) {
+        return getClassesForPackage(pkg, ClassEnumerator.class.getClassLoader());
+    }
+
+   /**
+    * Return all the classes in this package recursively.
+    *
+    * @param pkg the searched package
+    * @return list of full class names
+    */
+    public static SortedSet<String> getClassesForPackage(Package pkg, ClassLoader classLoader) {
+        SortedSet<String> classes = new TreeSet<String>(new Comparator<String>() {
+           public int compare(String o1, String o2) {
+              String simpleName1 = getSimpleName(o1);
+              String simpleName2 = getSimpleName(o2);
+              return simpleName1.compareTo(simpleName2);
+           }
+
+           private String getSimpleName(String className) {
+              return className.substring(className.lastIndexOf('.'));
+           }
+        });
+
+        String pkgname = pkg.getName();
+        String relPath = pkgname.replace('.', '/');
+
+        // Get a File object for the package
+        Enumeration<URL> resources;
+        try {
+            resources = classLoader.getResources(relPath);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        while(resources.hasMoreElements()) {
+            URL resource = resources.nextElement();
+            if (resource.toString().startsWith("jar:")) {
+                processJarfile(resource, pkgname, classes);
+            } else {
+                processDirectory(new File(resource.getPath()), pkgname, classes);
+            }
+        }
+
+        return classes;
+    }
+
+}
diff --git a/tck/src/main/java/org/objenesis/tck/search/SearchWorkingInstantiator.java b/tck/src/main/java/org/objenesis/tck/search/SearchWorkingInstantiator.java
new file mode 100644
index 0000000..5f11ff7
--- /dev/null
+++ b/tck/src/main/java/org/objenesis/tck/search/SearchWorkingInstantiator.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.tck.search;
+
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.objenesis.strategy.PlatformDescription;
+import org.objenesis.tck.candidates.SerializableNoConstructor;
+
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Iterator;
+import java.util.SortedSet;
+
+/**
+ * This class will try every available instantiator on the platform to see which works.
+ *
+ * @author Henri Tremblay
+ */
+public class SearchWorkingInstantiator implements Serializable { // implements Serializable just for the test
+
+    private SearchWorkingInstantiatorListener listener;
+
+    public static void main(String[] args) throws Exception {
+        System.out.println();
+        System.out.println(PlatformDescription.describePlatform());
+        System.out.println();
+
+        SearchWorkingInstantiator searchWorkingInstantiator = new SearchWorkingInstantiator(new SystemOutListener());
+        searchWorkingInstantiator.searchForInstantiator(SerializableNoConstructor.class);
+    }
+
+    public SearchWorkingInstantiator(SearchWorkingInstantiatorListener listener) {
+        this.listener = listener;
+    }
+
+    public void searchForInstantiator(Class<?> toInstantiate) {
+        SortedSet<String> classes = ClassEnumerator.getClassesForPackage(ObjectInstantiator.class.getPackage());
+
+        for (Iterator<String> it = classes.iterator(); it.hasNext();) {
+            String className = it.next();
+
+            // Skip if inner class of isn't named like a instantiator
+            if(className.contains("$") || !className.endsWith("Instantiator")) {
+               continue;
+            }
+
+           Class<?> c = null;
+           try {
+              c = Class.forName(className);
+           }
+           catch(Exception e) {
+              listener.instantiatorUnsupported(c, e);
+              continue;
+           }
+
+           if(c.isInterface() || !ObjectInstantiator.class.isAssignableFrom(c)) {
+                continue;
+           }
+
+            Constructor<?> constructor;
+            try {
+                constructor = c.getConstructor(Class.class);
+            } catch (NoSuchMethodException e) {
+                throw new RuntimeException(e);
+            }
+
+            try {
+                ObjectInstantiator<?> instantiator =
+                        (ObjectInstantiator<?>) constructor.newInstance(toInstantiate);
+                instantiator.newInstance();
+                listener.instantiatorSupported(c);
+            }
+            catch(Exception e) {
+                Throwable t = (e instanceof InvocationTargetException) ? e.getCause() : e;
+                listener.instantiatorUnsupported(c, t);
+            }
+        }
+    }
+}
diff --git a/main/src/main/java/org/objenesis/instantiator/NullInstantiator.java b/tck/src/main/java/org/objenesis/tck/search/SearchWorkingInstantiatorListener.java
similarity index 65%
copy from main/src/main/java/org/objenesis/instantiator/NullInstantiator.java
copy to tck/src/main/java/org/objenesis/tck/search/SearchWorkingInstantiatorListener.java
index ab2a44f..65214aa 100644
--- a/main/src/main/java/org/objenesis/instantiator/NullInstantiator.java
+++ b/tck/src/main/java/org/objenesis/tck/search/SearchWorkingInstantiatorListener.java
@@ -1,31 +1,26 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.instantiator;

-

-/**

- * The instantiator that always return a null instance

- * 

- * @author Henri Tremblay

- */

-public class NullInstantiator implements ObjectInstantiator {

-

-   /**

-    * @return Always null

-    */

-   public Object newInstance() {

-      return null;

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.tck.search;
+
+/**
+ * @author Henri Tremblay
+ */
+public interface SearchWorkingInstantiatorListener {
+
+    void instantiatorSupported(Class<?> c);
+
+    void instantiatorUnsupported(Class<?> c, Throwable t);
+}
diff --git a/tck/src/main/java/org/objenesis/tck/search/SystemOutListener.java b/tck/src/main/java/org/objenesis/tck/search/SystemOutListener.java
new file mode 100644
index 0000000..dcae640
--- /dev/null
+++ b/tck/src/main/java/org/objenesis/tck/search/SystemOutListener.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.tck.search;
+
+import org.objenesis.instantiator.annotations.Instantiator;
+import org.objenesis.instantiator.annotations.Typology;
+
+/**
+ * @author Henri Tremblay
+ */
+public class SystemOutListener implements SearchWorkingInstantiatorListener {
+
+    private static final String PATTERN = "%-65s: %s%n";
+
+    public void instantiatorSupported(Class<?> c) {
+        System.out.printf(PATTERN, c.getSimpleName() + " (" + getTypology(c) + ")", "Working!");
+    }
+
+    public void instantiatorUnsupported(Class<?> c, Throwable t) {
+        System.out.printf(PATTERN, c.getSimpleName() + "(" + getTypology(c) + ")", "KO - " + t);
+    }
+
+    private Typology getTypology(Class<?> c) {
+       Instantiator instantiatorAnn = c.getAnnotation(Instantiator.class);
+       return instantiatorAnn == null ? Typology.UNKNOWN : instantiatorAnn.value();
+    }
+}
diff --git a/tck/src/main/resources/org/objenesis/tck/candidates/candidates.properties b/tck/src/main/resources/org/objenesis/tck/candidates/candidates.properties
index 146c01d..41d74f8 100644
--- a/tck/src/main/resources/org/objenesis/tck/candidates/candidates.properties
+++ b/tck/src/main/resources/org/objenesis/tck/candidates/candidates.properties
@@ -1,5 +1,5 @@
 #
-# Copyright 2006-2013 the original author or authors.
+# Copyright 2006-2017 the original author or authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,42 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
+
 # List of candidate classes to attempt to instantiate in the Objenesis TCK.
 
 # Different visibilities of constructor.
@@ -62,11 +27,11 @@
 org.objenesis.tck.candidates.SerializableDefaultPackageConstructor              = Default package constructor (serializable)
 org.objenesis.tck.candidates.DefaultPrivateConstructor                          = Default private constructor
 org.objenesis.tck.candidates.SerializableDefaultPrivateConstructor              = Default private constructor (serializable)
-org.objenesis.tck.candidates.SerializableWithAncestorThrowingException			= Serializable with ancestor throwing exception
-org.objenesis.tck.candidates.SerializableReplacer								= Serializable replacing with another class
-org.objenesis.tck.candidates.SerializableResolver								= Serializable resolving to another class
+org.objenesis.tck.candidates.SerializableWithAncestorThrowingException          = Serializable with ancestor throwing exception
+org.objenesis.tck.candidates.SerializableReplacer                               = Serializable replacing with another class
+org.objenesis.tck.candidates.SerializableResolver                               = Serializable resolving to another class
 
-# Constructors that work with arguments passed in. 
+# Constructors that work with arguments passed in.
 org.objenesis.tck.candidates.ConstructorThrowingException                       = Constructor throwing exception
 org.objenesis.tck.candidates.SerializableConstructorThrowingException           = Constructor throwing exception (serializable)
 org.objenesis.tck.candidates.ConstructorWithArguments                           = Constructor with arguments
diff --git a/tck/src/main/resources/org/objenesis/tck/candidates/serializable-candidates.properties b/tck/src/main/resources/org/objenesis/tck/candidates/serializable-candidates.properties
index 33c03ea..365f152 100644
--- a/tck/src/main/resources/org/objenesis/tck/candidates/serializable-candidates.properties
+++ b/tck/src/main/resources/org/objenesis/tck/candidates/serializable-candidates.properties
@@ -1,5 +1,5 @@
 #
-# Copyright 2006-2013 the original author or authors.
+# Copyright 2006-2017 the original author or authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,42 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
+
 # List of candidate classes to attempt to instantiate in the Objenesis TCK.
 
 # Different visibilities of constructor.
@@ -57,10 +22,10 @@
 org.objenesis.tck.candidates.SerializableDefaultProtectedConstructor            = Default protected constructor (serializable)
 org.objenesis.tck.candidates.SerializableDefaultPackageConstructor              = Default package constructor (serializable)
 org.objenesis.tck.candidates.SerializableDefaultPrivateConstructor              = Default private constructor (serializable)
-org.objenesis.tck.candidates.SerializableReplacer								= Serializable replacing with another class
-org.objenesis.tck.candidates.SerializableResolver								= Serializable resolving to another class
+org.objenesis.tck.candidates.SerializableReplacer                               = Serializable replacing with another class
+org.objenesis.tck.candidates.SerializableResolver                               = Serializable resolving to another class
 
-# Constructors that work with arguments passed in. 
+# Constructors that work with arguments passed in.
 org.objenesis.tck.candidates.SerializableConstructorThrowingException           = Constructor throwing exception (serializable)
 org.objenesis.tck.candidates.SerializableConstructorWithArguments               = Constructor with arguments (serializable)
 org.objenesis.tck.candidates.SerializableConstructorWithMandatoryArguments      = Constructor with mandatory arguments (serializable)
diff --git a/tck/src/test/java/org/objenesis/tck/CandidateLoaderTest.java b/tck/src/test/java/org/objenesis/tck/CandidateLoaderTest.java
index 7c0666b..94c3c4f 100644
--- a/tck/src/test/java/org/objenesis/tck/CandidateLoaderTest.java
+++ b/tck/src/test/java/org/objenesis/tck/CandidateLoaderTest.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,25 +15,29 @@
  */
 package org.objenesis.tck;
 
+import static org.junit.Assert.*;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 
-import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
 
 /**
  * @author Joe Walnes
  */
-public class CandidateLoaderTest extends TestCase {
+public class CandidateLoaderTest {
 
-   private StringBuffer recordedEvents;
+   private StringBuilder recordedEvents;
    private CandidateLoader candidateLoader;
 
-   protected void setUp() throws Exception {
-      super.setUp();
+   @Before
+   public void setUp() throws Exception {
 
-      recordedEvents = new StringBuffer();
+      recordedEvents = new StringBuilder();
       TCK tck = new TCK() {
-         public void registerCandidate(Class candidateClass, String description) {
+         @Override
+         public void registerCandidate(Class<?> candidateClass, String description) {
             recordedEvents.append("registerCandidate('").append(candidateClass).append("', '")
                .append(description).append("')\n");
          }
@@ -47,6 +51,7 @@
       candidateLoader = new CandidateLoader(tck, getClass().getClassLoader(), errorHandler);
    }
 
+   @Test
    public void testReadsClassesAndDescriptionsFromPropertiesFile() throws IOException {
       String input = "" + "org.objenesis.tck.CandidateLoaderTest$A = A candidate\n" + "\n"
          + "# a comment and some whitespace\n" + "\n"
@@ -62,6 +67,7 @@
          recordedEvents.toString());
    }
 
+   @Test
    public void testReportsMissingClassesToErrorHandler() throws IOException {
       String input = "" + "org.objenesis.tck.CandidateLoaderTest$A = A candidate\n"
          + "org.objenesis.tck.CandidateLoaderTest$NonExistant = Dodgy candidate\n"
@@ -76,6 +82,7 @@
          recordedEvents.toString());
    }
 
+   @Test
    public void testLoadsFromResourceInClassPath() throws IOException {
       // See CandidateLoaderTest-sample.properties.
 
@@ -87,6 +94,7 @@
          recordedEvents.toString());
    }
 
+   @Test
    public void testThrowsIOExceptionIfResourceNotInClassPath() throws IOException {
       try {
          candidateLoader.loadFromResource(getClass(), "Blatently-Bogus.properties");
diff --git a/tck/src/test/java/org/objenesis/tck/ObjenesisTest.java b/tck/src/test/java/org/objenesis/tck/ObjenesisTest.java
index 95c3188..5b1073c 100644
--- a/tck/src/test/java/org/objenesis/tck/ObjenesisTest.java
+++ b/tck/src/test/java/org/objenesis/tck/ObjenesisTest.java
@@ -1,140 +1,90 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.tck;

-

-import java.io.ByteArrayOutputStream;

-import java.io.PrintStream;

-import java.io.Serializable;

-import java.util.Collection;

-

-import junit.framework.TestCase;

-

-import org.objenesis.ObjenesisSerializer;

-import org.objenesis.ObjenesisStd;

-

-/**

- * Integration test for Objenesis. Should pass successfully on every supported JVM for all Objenesis

- * interface implementation.

- * 

- * @author Henri Tremblay

- */

-public class ObjenesisTest extends TestCase {

-

-   public static class ErrorHandler implements CandidateLoader.ErrorHandler {

-      public void classNotFound(String name) {

-         fail("Class not found : " + name);

-      }

-   }

-

-   public static class JUnitReporter implements Reporter {

-

-      private String currentObjenesis;

-

-      private String currentCandidate;

-

-      public void startTests(String platformDescription, Collection allCandidates,

-         Collection allInstantiators) {

-      }

-

-      public void startTest(String candidateDescription, String objenesisDescription) {

-         currentCandidate = candidateDescription;

-         currentObjenesis = objenesisDescription;

-      }

-

-      public void endObjenesis(String description) {

-      }

-

-      public void endTests() {

-      }

-

-      public void exception(Exception exception) {

-         ByteArrayOutputStream buffer = new ByteArrayOutputStream();

-         PrintStream out = new PrintStream(buffer);

-         out.println("Exception when instantiating " + currentCandidate + " with "

-            + currentObjenesis + ": ");

-         exception.printStackTrace(out);

-         fail(buffer.toString());

-      }

-

-      public void result(boolean instantiatedObject) {

-         assertTrue("Instantiating " + currentCandidate + " with " + currentObjenesis + " failed",

-            instantiatedObject);

-      }

-

-      public void endTest() {

-      }

-   }

-   

-   static class MockSuperClass {

-	   private final boolean superConstructorCalled;

-	   public MockSuperClass() {

-		   superConstructorCalled = true;

-	   }

-	   public boolean isSuperConstructorCalled() {

-		   return superConstructorCalled;

-	   }

-   }

-   

-   static class MockClass extends MockSuperClass implements Serializable {

-      private static final long serialVersionUID = 1L;

-      private final boolean constructorCalled;

-	   public MockClass() {

-		   super();

-		   constructorCalled = true;

-	   }

-	   public boolean isConstructorCalled() {

-		   return constructorCalled;

-	   }

-   }

-

-   private TCK tck = null;

-

-   private CandidateLoader candidateLoader = null;

-

-   protected void setUp() throws Exception {

-      super.setUp();

-

-      tck = new TCK();

-

-      candidateLoader = new CandidateLoader(tck, getClass().getClassLoader(), new ErrorHandler());

-   }

-

-   protected void tearDown() throws Exception {

-      candidateLoader = null;

-      tck = null;

-      super.tearDown();

-   }

-

-   public void testObjenesisStd() throws Exception {

-      candidateLoader.loadFromResource(getClass(), "candidates/candidates.properties");

-      tck.registerObjenesisInstance(new ObjenesisStd(), "Objenesis standard");

-      tck.runTests(new JUnitReporter());

-   }

-

-   public void testObjenesisSerializer() throws Exception {

-      candidateLoader.loadFromResource(getClass(), "candidates/serializable-candidates.properties");

-      tck.registerObjenesisInstance(new ObjenesisSerializer(), "Objenesis serializer");

-      tck.runTests(new JUnitReporter());

-   }

-

-   public void testObjenesisSerializerParentConstructorCalled() throws Exception {

-   	  Object result = new ObjenesisSerializer().newInstance(MockClass.class);

-   	  assertEquals(MockClass.class, result.getClass());

-   	  MockClass mockObject = (MockClass) result;

-   	  assertTrue(mockObject.isSuperConstructorCalled());

-   	  assertFalse(mockObject.isConstructorCalled());   	  

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.tck;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Map;
+
+import org.junit.Test;
+import org.objenesis.ObjenesisSerializer;
+import org.objenesis.ObjenesisStd;
+
+/**
+ * Integration test for Objenesis. Should pass successfully on every supported JVM for all Objenesis
+ * interface implementation.
+ * 
+ * @author Henri Tremblay
+ */
+public class ObjenesisTest {
+
+   public static class JUnitReporter implements Reporter {
+
+      private String currentObjenesis;
+
+      private String currentCandidate;
+
+      public void startTests(String platformDescription, Map<String, Object> allCandidates,
+         Map<String, Object> allInstantiators) {
+      }
+
+      public void startTest(String candidateDescription, String objenesisDescription) {
+         currentCandidate = candidateDescription;
+         currentObjenesis = objenesisDescription;
+      }
+
+      public void endObjenesis(String description) {
+      }
+
+      public void endTests() {
+      }
+
+      public void exception(Exception exception) {
+         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+         PrintStream out = new PrintStream(buffer);
+         out.println("Exception when instantiating " + currentCandidate + " with "
+            + currentObjenesis + ": ");
+         exception.printStackTrace(out);
+         fail(buffer.toString());
+      }
+
+      public void result(boolean instantiatedObject) {
+         assertTrue("Instantiating " + currentCandidate + " with " + currentObjenesis + " failed",
+            instantiatedObject);
+      }
+
+      public void endTest() {
+      }
+   }
+
+   @Test
+   public void testObjenesisStd() throws Exception {
+      Main.runStandardTest(new ObjenesisStd(), new JUnitReporter());
+   }
+
+   @Test
+   public void testObjenesisSerializer() throws Exception {
+      Main.runSerializerTest(new ObjenesisSerializer(), new JUnitReporter());
+   }
+
+   @Test
+   public void testObjenesisSerializerParentConstructorCalled() throws Exception {
+      boolean result = Main.runParentConstructorTest(new ObjenesisSerializer());
+      assertTrue(result);
+   }
+}
diff --git a/tck/src/test/java/org/objenesis/tck/OsgiTest.java b/tck/src/test/java/org/objenesis/tck/OsgiTest.java
index 9679d71..d1e4b03 100644
--- a/tck/src/test/java/org/objenesis/tck/OsgiTest.java
+++ b/tck/src/test/java/org/objenesis/tck/OsgiTest.java
@@ -1,83 +1,100 @@
-/**

- * Copyright 2006-2013 the original author or authors.

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *     http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-package org.objenesis.tck;

-

-import java.io.File;

-import java.io.IOException;

-import java.io.Serializable;

-

-import javax.xml.parsers.DocumentBuilder;

-import javax.xml.parsers.DocumentBuilderFactory;

-import javax.xml.xpath.XPath;

-import javax.xml.xpath.XPathExpression;

-import javax.xml.xpath.XPathExpressionException;

-import javax.xml.xpath.XPathFactory;

-

-import org.objenesis.Objenesis;

-import org.objenesis.ObjenesisHelper;

-import org.springframework.osgi.test.AbstractConfigurableBundleCreatorTests;

-import org.w3c.dom.Document;

-

-/**

- * @author Henri Tremblay

- */

-public class OsgiTest extends AbstractConfigurableBundleCreatorTests implements Serializable {

-

-   private static final long serialVersionUID = 1L;

-

-   protected String[] getTestBundlesNames() {

-      String version = getImplementationVersion(Objenesis.class);

-      // Null means we are an IDE, not in Maven. So we have an IDE project dependency instead

-      // of a Maven dependency with the jar. Which explains why the version is null (no Manifest

-      // since there's no jar. In that case we get the version from the pom.xml and hope the Maven

-      // jar is up-to-date in the local repository

-      if(version == null) {

-         try {

-            XPathFactory xPathFactory = XPathFactory.newInstance();

-            final XPath xPath = xPathFactory.newXPath();

-            XPathExpression xPathExpression;

-            try {

-               xPathExpression = xPath.compile("/project/parent/version");

-            }

-            catch(final XPathExpressionException e) {

-               throw new RuntimeException(e);

-            }

-

-            final DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance();

-            xmlFact.setNamespaceAware(false);

-            final DocumentBuilder builder = xmlFact.newDocumentBuilder();

-            final Document doc = builder.parse(new File("pom.xml"));

-            version = xPathExpression.evaluate(doc);

-         }

-         catch(final Exception e) {

-            throw new RuntimeException(e);

-         }

-      }

-      return new String[] {"org.objenesis, objenesis, " + version};

-   }

-

-   public void testCanInstantiate() throws IOException {

-      assertSame(OsgiTest.class, ObjenesisHelper.newInstance(getClass()).getClass());

-   }

-

-   public void testCanInstantiateSerialize() throws IOException {

-      assertSame(OsgiTest.class, ObjenesisHelper.newSerializableInstance(getClass()).getClass());

-   }

-

-   protected String getImplementationVersion(final Class c) {

-      return c.getPackage().getImplementationVersion();

-   }

-}

+/**
+ * Copyright 2006-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.objenesis.tck;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.objenesis.Objenesis;
+import org.objenesis.ObjenesisHelper;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerMethod;
+import org.w3c.dom.Document;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import static org.junit.Assert.*;
+import static org.ops4j.pax.exam.CoreOptions.*;
+
+/**
+ * @author Henri Tremblay
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerMethod.class)
+public class OsgiTest implements Serializable{
+
+   private static final long serialVersionUID = 1L;
+
+   @Configuration
+   public Option[] config() {
+      String version = getImplementationVersion(Objenesis.class);
+      return options(
+         bundle("file:../main/target/objenesis-" + version + ".jar"),
+         junitBundles()
+      );
+   }
+
+   @Test
+   public void testCanInstantiate() throws IOException {
+      assertSame(OsgiTest.class, ObjenesisHelper.newInstance(getClass()).getClass());
+   }
+
+   @Test
+   public void testCanInstantiateSerialize() throws IOException {
+      assertSame(OsgiTest.class, ObjenesisHelper.newSerializableInstance(getClass()).getClass());
+   }
+
+   private String getImplementationVersion(final Class<?> c) {
+      String version = c.getPackage().getImplementationVersion();
+      // Null means we are an IDE, not in Maven. So we have an IDE project dependency instead
+      // of a Maven dependency with the jar. Which explains why the version is null (no Manifest
+      // since there's no jar). In that case we get the version from the pom.xml.
+      if(version == null) {
+         try {
+            XPathFactory xPathFactory = XPathFactory.newInstance();
+            final XPath xPath = xPathFactory.newXPath();
+            XPathExpression xPathExpression;
+            try {
+               xPathExpression = xPath.compile("/project/parent/version");
+            }
+            catch(final XPathExpressionException e) {
+               throw new RuntimeException(e);
+            }
+
+            final DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance();
+            xmlFact.setNamespaceAware(false);
+            final DocumentBuilder builder = xmlFact.newDocumentBuilder();
+            final Document doc = builder.parse(new File("pom.xml"));
+            version = xPathExpression.evaluate(doc);
+         }
+         catch(final Exception e) {
+            throw new RuntimeException(e);
+         }
+      }
+      return version;
+   }
+}
diff --git a/tck/src/test/java/org/objenesis/tck/TCKTest.java b/tck/src/test/java/org/objenesis/tck/TCKTest.java
index 89718dd..0af4f04 100644
--- a/tck/src/test/java/org/objenesis/tck/TCKTest.java
+++ b/tck/src/test/java/org/objenesis/tck/TCKTest.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,10 +15,11 @@
  */
 package org.objenesis.tck;
 
-import java.util.Collection;
+import static org.junit.Assert.*;
 
-import junit.framework.TestCase;
+import java.util.Map;
 
+import org.junit.Test;
 import org.objenesis.Objenesis;
 import org.objenesis.instantiator.ObjectInstantiator;
 
@@ -26,28 +27,29 @@
  * @author Joe Walnes
  * @author Henri Tremblay
  */
-public class TCKTest extends TestCase {
+public class TCKTest {
 
    public static class StubbedInstantiator1 implements Objenesis {
-      public Object newInstance(Class clazz) {
+      public <T> T newInstance(Class<T> clazz) {
          return null;
       }
 
-      public ObjectInstantiator getInstantiatorOf(Class clazz) {
+      public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) {
          return null;
       }
    }
 
    public static class StubbedInstantiator2 implements Objenesis {
-      public Object newInstance(Class clazz) {
+      public <T> T newInstance(Class<T> clazz) {
          return null;
       }
 
-      public ObjectInstantiator getInstantiatorOf(Class clazz) {
+      public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) {
          return null;
       }
    }
 
+   @Test
    public void testReportsAllCandidatesAndInstantiatorCombinationsToReporter() {
       // Given... a TCK with some candidate classes: A, B and C.
       TCK tck = new TCK();
@@ -75,6 +77,7 @@
          + "result(false)\n" + "endTest()\n" + "endTests()\n", reporter.toString());
    }
 
+   @Test
    public void testReportsSuccessIfCandidateCanBeInstantiated() {
       // Given... a TCK with some candidate classes: A, B and C.
       TCK tck = new TCK();
@@ -102,11 +105,11 @@
    // Some sample classes used for testing.
 
    public static class SelectiveInstantiator implements Objenesis {
-      public Object newInstance(Class clazz) {
-         return clazz == CandidateA.class ? new CandidateA() : null;
+      public <T> T newInstance(Class<T> clazz) {
+         return clazz.cast(clazz == CandidateA.class ? new CandidateA() : null);
       }
 
-      public ObjectInstantiator getInstantiatorOf(Class clazz) {
+      public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) {
          return null;
       }
    }
@@ -128,10 +131,10 @@
     */
    private static class RecordingReporter implements Reporter {
 
-      private final StringBuffer log = new StringBuffer();
+      private final StringBuilder log = new StringBuilder();
 
-      public void startTests(String platformDescription, Collection allCandidates,
-         Collection allInstantiators) {
+      public void startTests(String platformDescription, Map<String, Object> allCandidates,
+         Map<String, Object> allInstantiators) {
          log.append("startTests()\n");
       }
 
@@ -156,6 +159,7 @@
          log.append("endTests()\n");
       }
 
+      @Override
       public String toString() {
          return log.toString();
       }
diff --git a/tck/src/test/java/org/objenesis/tck/TextReporterTest.java b/tck/src/test/java/org/objenesis/tck/TextReporterTest.java
index f42093a..2a8b7c3 100644
--- a/tck/src/test/java/org/objenesis/tck/TextReporterTest.java
+++ b/tck/src/test/java/org/objenesis/tck/TextReporterTest.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2006-2013 the original author or authors.
+ * Copyright 2006-2017 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,32 +15,58 @@
  */
 package org.objenesis.tck;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.objenesis.Objenesis;
+import org.objenesis.ObjenesisBase;
+import org.objenesis.instantiator.basic.ConstructorInstantiator;
+import org.objenesis.instantiator.basic.FailingInstantiator;
+import org.objenesis.instantiator.basic.NullInstantiator;
+import org.objenesis.strategy.SingleInstantiatorStrategy;
+
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
-import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
 
 /**
  * @author Joe Walnes
  * @author Henri Tremblay
  */
-public class TextReporterTest extends TestCase {
+public class TextReporterTest {
 
    private TextReporter textReporter;
    private ByteArrayOutputStream summaryBuffer;
 
-   protected void setUp() throws Exception {
-      super.setUp();
+   @Before
+   public void setUp() throws Exception {
       summaryBuffer = new ByteArrayOutputStream();
       ByteArrayOutputStream logBuffer = new ByteArrayOutputStream();
       textReporter = new TextReporter(new PrintStream(summaryBuffer), new PrintStream(logBuffer));
    }
 
+   @Test
    public void testReportsSuccessesInTabularFormat() {
-      textReporter.startTests("Some platform", Arrays.asList(new String[] {"candidate A",
-         "candidate B", "candidate C"}), Arrays.asList(new String[] {"instantiator1",
-         "instantiator2", "instantiator3"}));
+      Map<String, Object> candidates = new HashMap<String, Object>();
+      candidates.put("candidate A", "A");
+      candidates.put("candidate B", "B");
+      candidates.put("candidate C", "C");
+      Map<String, Object> instantiators = new HashMap<String, Object>();
+
+      Objenesis instantiator1 = new ObjenesisBase(new SingleInstantiatorStrategy(
+         ConstructorInstantiator.class));
+      Objenesis instantiator2 = new ObjenesisBase(new SingleInstantiatorStrategy(
+         FailingInstantiator.class));
+      Objenesis instantiator3 = new ObjenesisBase(new SingleInstantiatorStrategy(
+         NullInstantiator.class));
+
+      instantiators.put("instantiator1", instantiator1);
+      instantiators.put("instantiator2", instantiator2);
+      instantiators.put("instantiator3", instantiator3);
+
+      textReporter.startTests("Some platform", candidates, instantiators);
 
       textReporter.startTest("candidate A", "instantiator1");
       textReporter.result(false);
@@ -71,7 +97,12 @@
       PrintStream out = new PrintStream(expectedSummaryBuffer);
       out.println("Running TCK on platform: Some platform");
       out.println();
-      out.println("Not serializable parent constructor called: Y");
+      out.println("Instantiators used: ");
+      out.println("   instantiator1: ConstructorInstantiator");
+      out.println("   instantiator2: FailingInstantiator");
+      out.println("   instantiator3: NullInstantiator");
+      out.println();
+      out.println("Not serializable parent constructor called as expected: Y");
       out.println();
       out.println("            instantiator1 instantiator2 instantiator3 ");
       out.println("candidate A n             n             Y             ");
diff --git a/tck/src/test/java/org/springframework/osgi/test/internal/boot-bundles.properties b/tck/src/test/java/org/springframework/osgi/test/internal/boot-bundles.properties
deleted file mode 100644
index 7d19172..0000000
--- a/tck/src/test/java/org/springframework/osgi/test/internal/boot-bundles.properties
+++ /dev/null
@@ -1,117 +0,0 @@
-#
-# Copyright 2006-2013 the original author or authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# START OF EDITION
-# This file is loaded by org.springframework.osgi.test.AbstractDependencyManagerTests. The
-# original file is located in spring-osgi-test-1.2.1.jar. Changes to the original are tagged
-# with "EDITED"
-# END OF EDITION
-#
-# Properties file indicating the boot (or mandatory) bundles that are loaded
-# by the testing framework.
-#
-# Normally, this file should not be edited since it is used by the testing infrastructure.
-# Users that want to install bundles before starting a test, should use #bundles() method.
-#
-
-#
-# format: <groupId,artifactId,version>=+/-15
-# - the optional value is used to install/remove bundles if running on JDK >= 1.5
-# - see Spring org.springframework.core.JdkVersion for jdk major version codes.
-
-# elements that have to be ignored should star with
-# ignore
-
-# Note: inner placeholders are not supported. 
-
-#
-# common properties
-#
-
-# versioning
-ignore.backport.version=3.1.0
-ignore.junit.version=3.8.2
-# EDITED: Upgrade the version from 1.2.15-SNAPSHOT to ${log4j.version}
-ignore.log4j.version=${log4j.version}
-
-ignore.spring.version=2.5.6.SEC01
-# EDITED: Filter the version to match the pom
-ignore.spring.osgi.version=${spring.osgi.version}
-# EDITED: Upgraded from 1.5.0
-ignore.slf4j.version=${slf4j.version}
-ignore.asm.version=2.2.3
-
-# groupIds
-ignore.spring.groupId=org.springframework
-ignore.spring.osgi.groupId=org.springframework.osgi
-ignore.slf4j.groupId=org.slf4j
-# EDITED: Switch from org.springframework.osgi to log4j 
-ignore.log4j.groupId=log4j
-
-#
-# actual libraries
-#
-# listed in dependency order to ease deployment
-
-
-# dependencies
-
-# junit
-org.junit,com.springsource.junit,${ignore.junit.version}=
-# log4j
-# EDITED: Change the groupId for log4j
-${ignore.log4j.groupId},log4j,${ignore.log4j.version}=
-# slf4j (commons-logging API)
-#${ignore.slf4j.groupId},slf4j-api,${ignore.slf4j.version}=
-#${ignore.slf4j.groupId},slf4j-log4j12,${ignore.slf4j.version}=
-#${ignore.slf4j.groupId},jcl104-over-slf4j,${ignore.slf4j.version}=
-# slf4j (BRITS)
-# EDITED: Change the groupId for and artifactId
-${ignore.slf4j.groupId},slf4j-api,${ignore.slf4j.version}=
-${ignore.slf4j.groupId},slf4j-log4j12,${ignore.slf4j.version}=
-${ignore.slf4j.groupId},jcl-over-slf4j,${ignore.slf4j.version}=
-# aop alliance
-org.aopalliance,com.springsource.org.aopalliance,1.0.0=
-# asm
-org.objectweb.asm,com.springsource.org.objectweb.asm,${ignore.asm.version}=
-# backport concurrent
-edu.emory.mathcs.backport,com.springsource.edu.emory.mathcs.backport,${ignore.backport.version}=-15
-
-# spring libs
-${ignore.spring.groupId},org.springframework.beans,${ignore.spring.version}=
-${ignore.spring.groupId},org.springframework.core,${ignore.spring.version}=
-${ignore.spring.groupId},org.springframework.context,${ignore.spring.version}=
-${ignore.spring.groupId},org.springframework.aop,${ignore.spring.version}=
-${ignore.spring.groupId},org.springframework.test,${ignore.spring.version}=
-
-
-# spring osgi libs
-${ignore.spring.osgi.groupId},spring-osgi-io,${ignore.spring.osgi.version}=
-${ignore.spring.osgi.groupId},spring-osgi-core,${ignore.spring.osgi.version}=
-${ignore.spring.osgi.groupId},spring-osgi-annotation,${ignore.spring.osgi.version}=+15
-${ignore.spring.osgi.groupId},spring-osgi-extender,${ignore.spring.osgi.version}=
-${ignore.spring.osgi.groupId},spring-osgi-test,${ignore.spring.osgi.version}=
diff --git a/tck/src/test/resources/logback-test.xml b/tck/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..96f5840
--- /dev/null
+++ b/tck/src/test/resources/logback-test.xml
@@ -0,0 +1,29 @@
+<!--
+
+    Copyright 2006-2017 the original author or authors.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="info">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
diff --git a/tck/src/test/resources/org/objenesis/tck/CandidateLoaderTest-sample.properties b/tck/src/test/resources/org/objenesis/tck/CandidateLoaderTest-sample.properties
index 14f8a6b..f07f593 100644
--- a/tck/src/test/resources/org/objenesis/tck/CandidateLoaderTest-sample.properties
+++ b/tck/src/test/resources/org/objenesis/tck/CandidateLoaderTest-sample.properties
@@ -1,5 +1,5 @@
 #
-# Copyright 2006-2013 the original author or authors.
+# Copyright 2006-2017 the original author or authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,43 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# See CandidateLoaderTest.java
 
+# See CandidateLoaderTest.java
 org.objenesis.tck.CandidateLoaderTest$A = A candidate
 org.objenesis.tck.CandidateLoaderTest$B = B candidate
\ No newline at end of file
diff --git a/tck/test/log4j.properties b/tck/test/log4j.properties
deleted file mode 100644
index 5a5db6b..0000000
--- a/tck/test/log4j.properties
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright 2006-2013 the original author or authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.layout.ConversionPattern=%p [%c] - %m%n
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-
-log4j.rootCategory=WARN, stdout
-
-# Uncomment to add logs
-#log4j.logger.org.easymock.itests.OsgiTest=TRACE, stdout