av9ash/GitBugs huggingface dataset:
Bug: SQL Expression traits don't compose due to nodePatterns being final.
Status: In Progress | Priority: Major | Resolution: 
Created: 03/May/22 00:05
Affects Version/s: 3.2.0

In Spark 3.1 I have an expression which contains these parts:
{code:scala}
case class MyExploder(
  arrays: Expression,    // Array[AnyDataType]
  asOfDate: Expression,  // LambdaFunction[AnyDataType -> TimestampType]
  extractor: Expression, // TimestampType
) extends HigherOrderFunction with Generator with TimeZoneAwareExpression {

 override def arguments: Seq[Expression] =
  Seq(arrays, asOfDate)

 override def argumentTypes: Seq[AbstractDataType] =
  Seq(ArrayType, TimestampType)

 override def functions: Seq[Expression] =
  Seq(extractor)

 override def functionTypes =
  Seq(TimestampType)
}{code}
 

This is grossly simplified example. The extractor is a lambda which can gather information from a nested array, and explodes based on some business logic.

When upgrading to Spark 3.2 however this can't work anymore, because they have conflicting final values for nodePatterns.
{code:java}
trait HigherOrderFunction extends Expression with ExpectsInputTypes {
 final override val nodePatterns: Seq[TreePattern] = Seq(HIGH_ORDER_FUNCTION)
}           {code}
 

We get this errror.
{noformat}
value nodePatterns in trait TimeZoneAwareExpression of type Seq[org.apache.spark.sql.catalyst.trees.TreePattern.TreePattern] cannot override final member{noformat}
 

This blocks us from upgrading. What's doubly annoying is that the actual value of the member appears to be the same.

 

Thank you for your time.
Bug: Move error message of INCONSISTENT_BEHAVIOR_CROSS_VERSION to the json file
Status: Resolved | Priority: Major | Resolution: Fixed
Created: 02/May/22 06:20
Affects Version/s: 3.4.0

Move the error message of the error class INCONSISTENT_BEHAVIOR_CROSS_VERSION from source code to the json file error-classes.json to for maintainability and easier translation to other languages (if it will be needed).
Bug: AddJar or AddFile call on a duplicate file should not result in failure
Status: Closed | Priority: Major | Resolution: Invalid
Created: 02/May/22 22:09
Affects Version/s: 3.1.0

Currently, when addFile or addJar is used to upload a file or a jar which was already uploaded, it should +not+ result in IOException. This is because the spark-submit behavior is to ignore adding duplicate jars/files and logging appropriate warning message. The same should be done for addFile and addJar APIs in Livy.
Bug: Fix FsHistoryProvider race condition between update and clean app data
Status: Resolved | Priority: Major | Resolution: Duplicate
Created: 02/May/22 05:17
Affects Version/s: 3.1.2

After SPARK-29043, FsHistoryProvider will list the log info without waitting all `mergeApplicationListing` task finished.

However the `LevelDBIterator` of list log info is not thread safe if some other threads delete the related log info at same time.

There is the error msg:
{code:java}
21/12/15 14:12:02 ERROR FsHistoryProvider: Exception in checking for event log updates
java.util.NoSuchElementException: 1^@__main__^@+hdfs://xxx/application_xxx.inprogress
        at org.apache.spark.util.kvstore.LevelDB.get(LevelDB.java:132)
        at org.apache.spark.util.kvstore.LevelDBIterator.next(LevelDBIterator.java:137)
        at scala.collection.convert.Wrappers$JIteratorWrapper.next(Wrappers.scala:44)
        at scala.collection.Iterator.foreach(Iterator.scala:941)
        at scala.collection.Iterator.foreach$(Iterator.scala:941)
        at scala.collection.AbstractIterator.foreach(Iterator.scala:1429)
        at scala.collection.IterableLike.foreach(IterableLike.scala:74)
        at scala.collection.IterableLike.foreach$(IterableLike.scala:73)
        at scala.collection.AbstractIterable.foreach(Iterable.scala:56)
        at scala.collection.generic.Growable.$plus$plus$eq(Growable.scala:62)
        at scala.collection.generic.Growable.$plus$plus$eq$(Growable.scala:53)
        at scala.collection.mutable.ListBuffer.$plus$plus$eq(ListBuffer.scala:184)
        at scala.collection.mutable.ListBuffer.$plus$plus$eq(ListBuffer.scala:47)
        at scala.collection.TraversableLike.to(TraversableLike.scala:678)
        at scala.collection.TraversableLike.to$(TraversableLike.scala:675)
        at scala.collection.AbstractTraversable.to(Traversable.scala:108)
        at scala.collection.TraversableOnce.toList(TraversableOnce.scala:299)
        at scala.collection.TraversableOnce.toList$(TraversableOnce.scala:299)
        at scala.collection.AbstractTraversable.toList(Traversable.scala:108)
        at org.apache.spark.deploy.history.FsHistoryProvider.checkForLogs(FsHistoryProvider.scala:588)
        at org.apache.spark.deploy.history.FsHistoryProvider.$anonfun$startPolling$3(FsHistoryProvider.scala:299)
{code}
Bug: Type overloads in `pandas_udf` 
Status: In Progress | Priority: Minor | Resolution: 
Created: 10/May/22 16:38
Affects Version/s: 3.2.1

It seems that the `returnType` in the type overloads for `pandas_udf` never specify a generic for PySpark SQL types or explicitly list those types:

 

[https://github.com/apache/spark/blob/f84018a4810867afa84658fec76494aaae6d57fc/python/pyspark/sql/pandas/functions.pyi]

 

This results in static type checkers flagging the type of the decorated functions (and their parameters) as incorrect, see [https://github.com/microsoft/pylance-release/issues/2789] as an example.

 

For someone familiar with the code base, this should be a very fast patch.
Bug: Test the error class: PIVOT_VALUE_DATA_TYPE_MISMATCH
Status: Resolved | Priority: Minor | Resolution: Duplicate
Created: 04/May/22 18:52
Affects Version/s: 3.4.0

Add tests for the error classes *PIVOT_VALUE_DATA_TYPE_MISMATCH* to QueryCompilationErrorsSuite. The test should cover the exception throw in QueryCompilationErrors:
{code:scala}
  def pivotValDataTypeMismatchError(pivotVal: Expression, pivotCol: Expression): Throwable = {
    new AnalysisException(
      errorClass = "PIVOT_VALUE_DATA_TYPE_MISMATCH",
      messageParameters = Array(
        pivotVal.toString, pivotVal.dataType.simpleString, pivotCol.dataType.catalogString))
  }
{code}
For example, here is a test for the error class {*}UNSUPPORTED_FEATURE{*}: [https://github.com/apache/spark/blob/34e3029a43d2a8241f70f2343be8285cb7f231b9/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala#L151-L170]

+The test must have a check of:+
 # the entire error message
 # sqlState if it is defined in the error-classes.json file
 # the error class
Bug: Speed up Timestamp type inference with user-provided format in JSON/CSV data source
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 25/May/22 02:51
Affects Version/s: 3.4.0

The optimization of {{DefaultTimestampFormatter}} has been implemented in [#36562|https://github.com/apache/spark/pull/36562] , this ticket adds the optimization of user-provided format. The basic logic is to prevent the formatter from throwing exceptions, and then use catch to determine whether the parsing is successful.
Bug: Upgrade Apache Xerces Java to 2.12.2
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 13/May/22 17:09
Affects Version/s: 3.2.1

[Infinite Loop in Apache Xerces Java |https://github.com/advisories/GHSA-h65f-jvqw-m9fj]

There's a vulnerability within the Apache Xerces Java (XercesJ) XML parser when handling specially crafted XML document payloads. This causes, the XercesJ XML parser to wait in an infinite loop, which may sometimes consume system resources for prolonged duration. This vulnerability is present within XercesJ version 2.12.1 and the previous versions.

References
https://nvd.nist.gov/vuln/detail/CVE-2022-23437
https://lists.apache.org/thread/6pjwm10bb69kq955fzr1n0nflnjd27dl
http://www.openwall.com/lists/oss-security/2022/01/24/3
https://www.oracle.com/security-alerts/cpuapr2022.html
Bug: Replcace `Array.toString` with `Array.mkString`
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 26/May/22 02:08
Affects Version/s: 3.4.0

Some code in Spark as follows:
{code:java}
val appDirs = workDir.listFiles()
if (appDirs == null) {
  throw new IOException("ERROR: Failed to list files in " + appDirs)
} {code}
appDirs is an `Array` and `Array.toString` will print as `className#hashCode`, this result seems meaningless and  Array.mkString should be used.
Bug: Replace the usage of  guava's Files.createTempDir() with java.nio.file.Files.createTempDirectory()
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 05/May/22 05:43
Affects Version/s: 3.2.0

Hi 

There are several classes where Spark is using guava's Files.createTempDir() which have vulnerabilities. I think its better to move to java.nio.file.Files.createTempDirectory() for those classes. 

Classes 

Java8RDDAPISuite

JavaAPISuite.java

RPackageUtilsSuite

StreamTestHelper

TestShuffleDataContext

ExternalBlockHandlerSuite
Bug: The singleton Jackson ObjectMapper should be preferred
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 11/May/22 06:54
Affects Version/s: 3.4.0

I write a mirco-benchmark to test Jackson ObjectWriter read and write:

[https://github.com/LuciferYang/spark/blob/objectMapper/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/JacksonBenchmark.scala]

and run this use GA:

 
{code:java}
OpenJDK 64-Bit Server VM 1.8.0_332-b09 on Linux 5.13.0-1022-azure
Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz
Test create ObjectMapper:                 Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
------------------------------------------------------------------------------------------------------------------------
Test create ObjectMapper                            648            652           4          0.0       64819.0       1.0XOpenJDK 64-Bit Server VM 1.8.0_332-b09 on Linux 5.13.0-1022-azure
Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz
Test write map to json:                   Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
------------------------------------------------------------------------------------------------------------------------
Test Multiple                                      2116           2127          15          0.0      211556.5       1.0X
Test Single                                           4              4           0          2.4         416.1     508.4XOpenJDK 64-Bit Server VM 1.8.0_332-b09 on Linux 5.13.0-1022-azure
Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz
Test read json to map:                    Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
------------------------------------------------------------------------------------------------------------------------
Test Multiple                                      8848           8867          27          0.0      884776.2       1.0X
Test Single   {code}
 

 

From the test results, we should use singleton Jackson ObjectMapper, because it seems expensive to new a ObjectMapper instance.

 

The following code in Spark not use singleton:

 
{code:java}
common/network-shuffle/src/main/java/org/apache/spark/network/shuffle/RemoteBlockPushResolver.java
core/src/main/scala/org/apache/spark/status/api/v1/JacksonMessageWriter.scala
core/src/main/scala/org/apache/spark/storage/DiskBlockManager.scala
resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/SparkKubernetesClientFactory.scala
sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/FileDataSourceV2.scala
sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DataSourceV2Utils.scala
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/RebaseDateTime.scala {code}
can find hotpath and fix them
Bug: Change to use `ConstantColumnVector` to store partition columns in `VectorizedParquetRecordReader`
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 19/May/22 04:19
Affects Version/s: 3.4.0

Try to use `ConstantColumnVector` instead of OnHeapColumnVector(or OffHeapColumnVector) to store partition columns in `VectorizedParquetRecordReader` for performance improvements and memory savings.

I will do some preliminary research and supplement jira description.

 

`
Bug: Spark SQL - wrong field selection in group by
Status: Resolved | Priority: Minor | Resolution: Not A Bug
Created: 26/May/22 07:09
Affects Version/s: 3.1.2

SQL parser select wrong field to group by.
See following example.
Sample data:

 
{code:java}
spark.sql("""
            select "US" as pv_countryCode
            union all
            select "IL" as pv_countryCode
         """).createOrReplaceTempView("my_test_data")
spark.sql("""
            select -3 as id, "US" as countryCode
         """).createOrReplaceTempView("country_codes_sample")
          {code}
code:
{code:java}
         
spark.sql("""
WITH BASE
  (SELECT
  pv_countryCode AS country_id
   FROM my_test_data)
    SELECT 
                COALESCE(cct.id, -3) as country_id, 
                count(1)  as count 
                FROM BASE 
                LEFT JOIN country_codes_sample cct ON cct.countryCode = country_id
                GROUP BY 
                         country_id
         """).createOrReplaceTempView("campaign_country_bug")           {code}
Error:
{code:java}
org.apache.spark.sql.AnalysisException: expression 'cct.`id`' is neither present in the group by, nor is it an aggregate function. Add to group by or wrap in first() (or first_value) if you don't care which value you get.;
Aggregate [country_id#910], [coalesce(id#886, -3) AS country_id#908, count(1) AS count#909L]
+- Join LeftOuter, (countryCode#887 = country_id#910)
   :- SubqueryAlias BASE
   :  +- Project [pv_countryCode#883 AS country_id#910]
   :     +- SubqueryAlias my_test_data
   :        +- Union false, false
   :           :- Project [US AS pv_countryCode#883]
   :           :  +- OneRowRelation
   :           +- Project [IL AS pv_countryCode#884]
   :              +- OneRowRelation
   +- SubqueryAlias cct
      +- SubqueryAlias country_codes_sample
         +- Project [-3 AS id#886, US AS countryCode#887]
            +- OneRowRelation {code}
I expected Spark to choose the selected country_id(country_id#908) instead of country_id#910

Or at least throw ambiguous exception when grouping by `country_id`.

This lead developers to add `cct.id` into group by which results in unexpected results.
(In case country_id has both null and -3 values)
Bug: Need Support for avro 1.11.0 in apache spark
Status: Resolved | Priority: Minor | Resolution: Duplicate
Created: 11/May/22 13:48
Affects Version/s: 3.1.2

There is apache avro foss compliance issue in older version of avro, 1.8.2, this is resolved from1.10.0 but we needed newer version 1.11.0 to be support in spark, since spark is based on 1.8.2 and 1.11.0 has major changes with respect to java.time.* package, our manual change of version upgrade is not working.
Bug: After eliminating join to one side, that side should take advantage of LocalShuffleRead optimization
Status: In Progress | Priority: Minor | Resolution: 
Created: 09/May/22 03:54
Affects Version/s: 3.2.1

PropagateEmptyRelation can simplify Join. For example, if the right side of LEFT JOIN is empty, then it can eliminate join to its left side.

If there is a shuffle on the left side, it can be considered that the shuffle is meaningless, and the shuffle can be optimized by using LocalRead.
Bug: Clean up dsl unnecessary symbol
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 24/May/22 01:16
Affects Version/s: 3.4.0

dsl is a test helper file which provide easy used functions. But some of these are unnecessary, for example:
{code:java}
def subquery(alias: Symbol): LogicalPlan {code}
For a subquery, we only need the name, so a string type parameter is enough.
Bug: Change to exclude `slf4j-reload4j` for `hadoop-minikdc`
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 30/May/22 03:31
Affects Version/s: 3.4.0

HADOOP-18088 Replace log4j 1.x with reload4j in Hadoop 3.3.3 and there will be waring log when in Spark when test

{code}
Testing started at 10:11 ...
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/yangjie01/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.17.2/log4j-slf4j-impl-2.17.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/yangjie01/.m2/repository/org/slf4j/slf4j-reload4j/1.7.36/slf4j-reload4j-1.7.36.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
{code}
Bug: Only disable bucketing when autoBucketedScan is enabled if bucket columns are not in scan output
Status: In Progress | Priority: Minor | Resolution: 
Created: 31/May/22 05:11
Affects Version/s: 3.3.0

Currently, bucketing was disabled when bucket columns are not in scan output after https://github.com/apache/spark/pull/27924. It break existing applications whose input size is huge by creating too many FilePartitions and causing driver hang. And it cannot be switched off. This is to propose merging the rule into DisableUnnecessaryBucketedScan.
Bug: Hide empty `taskResourceAssignments` from INFO log
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 27/May/22 23:44
Affects Version/s: 3.4.0

This issue aims to hide empty `taskResourceAssignments` info from the INFO log.
{code}
22/05/27 23:41:21 INFO TaskSetManager: Starting task 70587.0 in stage 0.0 (TID 70587) (100.97.198.216, executor 1, partition 70587, PROCESS_LOCAL, 4452 bytes) taskResourceAssignments Map()
22/05/27 23:41:21 INFO TaskSetManager: Finished task 70571.0 in stage 0.0 (TID 70571) in 99 ms on 100.97.198.216 (executor 1) (70569/300000)
{code}
Bug: ui error if spark.ui.proxyBase contains "proxy" or "history"
Status: In Progress | Priority: Minor | Resolution: 
Created: 26/May/22 03:08
Affects Version/s: 3.4.0

ui try to get app id after words "proxy" or "history", 

check files 

[https://github.com/apache/spark/blob/master/core/src/main/resources/org/apache/spark/ui/static/utils.js#L187]

however, if user reverse proxy contains words "proxy" or "history", the ui will get wrong app id, 404 error will happen
Bug: Alternative configs of Hadoop Filesystems to access break backward compatibility
Status: In Progress | Priority: Minor | Resolution: 
Created: 25/May/22 01:37
Affects Version/s: 3.3.0

Before [https://github.com/apache/spark/pull/23698,]

The precedence of configuring Hadoop Filesystems to access is
{code:java}
spark.yarn.access.hadoopFileSystems -> spark.yarn.access.namenodes{code}
Afterwards, it's
{code:java}
spark.kerberos.access.hadoopFileSystems -> spark.yarn.access.namenodes -> spark.yarn.access.hadoopFileSystems{code}
When both spark.yarn.access.hadoopFileSystems and spark.yarn.access.namenodes are configured with different values, the PR will break backward compatibility and cause application failure.
Bug: Improve subexpression elimination for conditional expressions
Status: In Progress | Priority: Minor | Resolution: 
Created: 21/May/22 13:32
Affects Version/s: 3.4.0

Currently we can do subexpression elimination for conditional expressions when the subexpression is common across all {{{}branchGroups{}}}. In fact, we can farther improve this when there are common expressions between {{alwaysEvaluatedInputs}} and {{{}branchGroups{}}}.
Bug: Introduce a `putByteArrays` method to `WritableColumnVector` to support setting multiple duplicate `byte[]`
Status: Resolved | Priority: Minor | Resolution: Won't Fix
Created: 17/May/22 02:51
Affects Version/s: 3.4.0

Add a  `putByteArrays` method to `WritableColumnVector`

 
{code:java}
int putByteArrays(int rowId, int total, byte[] value) {code}
 

 

this method used to support setting multiple duplicate `byte[]` to `WritableColumnVector`.

Since `byte[] value` is fixed length, memory can allocated at one time without calling `

reserve(int requiredCapacity)` method many times.

 

This method is applicable to `ColumnVectorUtils.populate` method with `StringType` and partial `DecimalType` scenario, this corresponds to the Vectorized Partition Column filling of Parquet and Orc
Bug: Dividing interval by integral can result in codegen compilation error
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 03/May/22 16:13
Affects Version/s: 3.2.1

Assume this data:
{noformat}
create or replace temp view v1 as
select * FROM VALUES
(interval '10' months, interval '10' day, 2)
as v1(period, duration, num);

cache table v1;
{noformat}
These two queries work:
{noformat}
spark-sql> select period/num from v1;
0-5
Time taken: 0.143 seconds, Fetched 1 row(s)
{noformat}
{noformat}
spark-sql> select duration/num from v1;
5 00:00:00.000000000
Time taken: 0.094 seconds, Fetched 1 row(s)
{noformat}
However, these two queries get a codegen compilation error:
{noformat}
spark-sql> select period/(num + 3) from v1;
22/05/03 08:56:37 ERROR CodeGenerator: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 40, Column 44: Expression "project_value_2" is not an rvalue
...
22/05/03 08:56:37 WARN UnsafeProjection: Expr codegen error and falling back to interpreter mode
...
0-2
Time taken: 0.149 seconds, Fetched 1 row(s)
{noformat}
{noformat}
spark-sql> select duration/(num + 3) from v1;
22/05/03 08:57:29 ERROR CodeGenerator: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 40, Column 54: Expression "project_value_2" is not an rvalue
...
22/05/03 08:57:29 WARN UnsafeProjection: Expr codegen error and falling back to interpreter mode
...
2 00:00:00.000000000
Time taken: 0.089 seconds, Fetched 1 row(s)
{noformat}
Even the first two queries will get a compilation error if you turn off whole-stage codegen:
{noformat}
spark-sql> set spark.sql.codegen.wholeStage=false;
spark.sql.codegen.wholeStage	false
Time taken: 0.055 seconds, Fetched 1 row(s)
spark-sql> select period/num from v1;
22/05/03 09:16:42 ERROR CodeGenerator: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 37, Column 5: Expression "value_1" is not an rvalue
....
0-5
Time taken: 0.175 seconds, Fetched 1 row(s)
spark-sql> select duration/num from v1;
22/05/03 09:17:41 ERROR CodeGenerator: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 37, Column 5: Expression "value_1" is not an rvalue
...
5 00:00:00.000000000
Time taken: 0.104 seconds, Fetched 1 row(s)
{noformat}
Note that in the error cases, the queries still return a result because Spark falls back on interpreting the divide expression (so I marked this as "minor").
Bug: Fix potential risk of LevelDBIterator leak
Status: In Progress | Priority: Minor | Resolution: 
Created: 09/May/22 04:34
Affects Version/s: 3.4.0

Similar as SPARK-39063

There is lock contention between `LevelDBIterator.finalize()` and `LevalDb.close()` method. If `LevelDB.close()` method is executed first, the `LevelDBIterator`s hold by `Finalizer` will not close before the `LevelDB` close.
Bug: Upgrade `org.scalatestplus:mockito` to 3.2.12.0
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 07/May/22 09:19
Affects Version/s: 3.4.0

`mockito-4-2_${scala.binary.version}:3.2.11.0` -> `mockito-4-5_${scala.binary.version}:3.2.12.0`

 

mockito 4.2.0 -> 4.5.1
Bug: Mark overriden methods with `@override` annotation
Status: Resolved | Priority: Minor | Resolution: Fixed
Created: 06/May/22 02:49
Affects Version/s: 2.3.0

An overridden method from an interface or abstract class must be marked with {{@Override}} annotation. To accurately determine whether the overriding is successful, an {{@Override}} annotation is necessary. Meanwhile, once the method signature in the abstract class is changed, the implementation class will report a compile-time error immediately.